最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Vue.js can't find element using querySelector - Stack Overflow

programmeradmin0浏览0评论

I am trying to create a chat style form. So a user inputs their data and then uses the button within my template with the class of continue-btn.

As you can see when the continue-btn is pressed it uses the nextStep method which adds 1 to the counter data property.

Within my template I then use v-if="counter >= 1" to display the next section of the chat dialog and input field.

I am then trying to use scrollTop to automatically scroll the page to the new section with the id of #conversation__tram-1. I originally tried running this block of code just after the counter had been given a value of 1:

const container = this.$el.querySelector("#conversation__tram-" + this.counter);
container.scrollTop = container.scrollHeight;

This didn't work though because I'm guessing the #conversation__tram-1 element hadn't been added to the DOM yet.

So for the sake of testing I tried wrapping it in a timeout function:

  setTimeout(function(){
    const container = this.$el.querySelector("#conversation__tram-" + this.counter);
    container.scrollTop = container.scrollHeight;
  }, 3000);

However I am left with this error when trying this:

Uncaught TypeError: Cannot read property 'querySelector' of undefined

Here is my whole single vue file:

<template>

    <div id="conversation-app">
      <!-- <div v-for="item in items">
        {{ item.text }}
      </div> -->
      <div class="conversation__track">
        <div id="conversation__tram-0">
          <div class="conversation__item agent">
            <img src="/assets/cdn.annuityadvicecentre.dev/images/theme-f/michael-chat-agent.jpg" class="conversation__item-prof-img" alt="Michael Chat Agent" />
            <div class="conversation__item-content">
              <p>
                Hello my name is {{ agent }}, we'll compare the whole annuity market to bring you back the best annuity rates from the top providers for you. Let's get started, what's your name?
              </p>
            </div>
          </div>
          <div class="conversation__item customer" id="title-fullname">
            <div class="conversation__item-content">
              <p>
                Hi {{ agent }}, my name is...
              </p>
              <div class="row">
                <div class="col-4">
                  <select id="title" class="field-title" name="payload[title]"><option value="mr">Mr</option><option value="mrs">Mrs</option><option value="miss">Miss</option><option value="ms">Ms</option></select>
                </div>
                <div class="col-8">
                  <input v-model="customerName" id="full_name" class="field-full_name" name="payload[full_name]" type="text">
                </div>
              </div>
            </div>
          </div>
        </div>
        <transition name="fade">
          <div id="conversation__tram-1" v-if="counter >= 1">
            <div class="conversation__item agent">
              <img src="/assets/cdn.annuityadvicecentre.dev/images/theme-f/michael-chat-agent.jpg" class="conversation__item-prof-img" alt="Michael Chat Agent" />
              <div class="conversation__item-content">
                <p>
                  Thanks {{ firstName }}, nice to meet you. To process your instant quote please can I have your Pension Value?
                </p>
              </div>
            </div>
            <div class="conversation__item customer">
              <div class="conversation__item-content">
                <p>
                  Sure, my pension value is...
                </p>
                <input id="pension_value" class="field-pension_value" placeholder="£" pattern="\d*" name="payload[pension_value]" type="number">
                <div class="error-wrap error_pension_value is-hidden" data-format="<div class=&quot;error-text&quot;>:message</div>"></div>
              </div>
            </div>
          </div>
        </transition>
        <div id="conversation__buttons">
          <button type="button" class="continue-btn"
          v-on:click="nextStep"
          >Continue&nbsp;<i class="fa fa-chevron-right" aria-hidden="true"></i></button>
        </div>
      </div>
    </div>
</template>

<script>
export default {
  name: 'conversation-app',
  data () {
    return {
      agent: 'Brick',
      counter: 0,
      customerName: '',
    }
  },
  methods: {
    nextStep: function() {
      this.counter += 1;
      setTimeout(function(){
        const container = this.$el.querySelector("#conversation__tram-" + this.counter);
        container.scrollTop = container.scrollHeight;
      }, 3000);

    },
  },
  computed: {
    firstName() {
      return this.customerName.split(' ')[0];
    }
  }
}
</script>

Any idea why this isn't working? Thanks.

I am trying to create a chat style form. So a user inputs their data and then uses the button within my template with the class of continue-btn.

As you can see when the continue-btn is pressed it uses the nextStep method which adds 1 to the counter data property.

Within my template I then use v-if="counter >= 1" to display the next section of the chat dialog and input field.

I am then trying to use scrollTop to automatically scroll the page to the new section with the id of #conversation__tram-1. I originally tried running this block of code just after the counter had been given a value of 1:

const container = this.$el.querySelector("#conversation__tram-" + this.counter);
container.scrollTop = container.scrollHeight;

This didn't work though because I'm guessing the #conversation__tram-1 element hadn't been added to the DOM yet.

So for the sake of testing I tried wrapping it in a timeout function:

  setTimeout(function(){
    const container = this.$el.querySelector("#conversation__tram-" + this.counter);
    container.scrollTop = container.scrollHeight;
  }, 3000);

However I am left with this error when trying this:

Uncaught TypeError: Cannot read property 'querySelector' of undefined

Here is my whole single vue file:

<template>

    <div id="conversation-app">
      <!-- <div v-for="item in items">
        {{ item.text }}
      </div> -->
      <div class="conversation__track">
        <div id="conversation__tram-0">
          <div class="conversation__item agent">
            <img src="/assets/cdn.annuityadvicecentre.dev/images/theme-f/michael-chat-agent.jpg" class="conversation__item-prof-img" alt="Michael Chat Agent" />
            <div class="conversation__item-content">
              <p>
                Hello my name is {{ agent }}, we'll compare the whole annuity market to bring you back the best annuity rates from the top providers for you. Let's get started, what's your name?
              </p>
            </div>
          </div>
          <div class="conversation__item customer" id="title-fullname">
            <div class="conversation__item-content">
              <p>
                Hi {{ agent }}, my name is...
              </p>
              <div class="row">
                <div class="col-4">
                  <select id="title" class="field-title" name="payload[title]"><option value="mr">Mr</option><option value="mrs">Mrs</option><option value="miss">Miss</option><option value="ms">Ms</option></select>
                </div>
                <div class="col-8">
                  <input v-model="customerName" id="full_name" class="field-full_name" name="payload[full_name]" type="text">
                </div>
              </div>
            </div>
          </div>
        </div>
        <transition name="fade">
          <div id="conversation__tram-1" v-if="counter >= 1">
            <div class="conversation__item agent">
              <img src="/assets/cdn.annuityadvicecentre.dev/images/theme-f/michael-chat-agent.jpg" class="conversation__item-prof-img" alt="Michael Chat Agent" />
              <div class="conversation__item-content">
                <p>
                  Thanks {{ firstName }}, nice to meet you. To process your instant quote please can I have your Pension Value?
                </p>
              </div>
            </div>
            <div class="conversation__item customer">
              <div class="conversation__item-content">
                <p>
                  Sure, my pension value is...
                </p>
                <input id="pension_value" class="field-pension_value" placeholder="£" pattern="\d*" name="payload[pension_value]" type="number">
                <div class="error-wrap error_pension_value is-hidden" data-format="<div class=&quot;error-text&quot;>:message</div>"></div>
              </div>
            </div>
          </div>
        </transition>
        <div id="conversation__buttons">
          <button type="button" class="continue-btn"
          v-on:click="nextStep"
          >Continue&nbsp;<i class="fa fa-chevron-right" aria-hidden="true"></i></button>
        </div>
      </div>
    </div>
</template>

<script>
export default {
  name: 'conversation-app',
  data () {
    return {
      agent: 'Brick',
      counter: 0,
      customerName: '',
    }
  },
  methods: {
    nextStep: function() {
      this.counter += 1;
      setTimeout(function(){
        const container = this.$el.querySelector("#conversation__tram-" + this.counter);
        container.scrollTop = container.scrollHeight;
      }, 3000);

    },
  },
  computed: {
    firstName() {
      return this.customerName.split(' ')[0];
    }
  }
}
</script>

Any idea why this isn't working? Thanks.

Share Improve this question asked May 30, 2017 at 9:48 Nick MaddrenNick Maddren 6614 gold badges9 silver badges20 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 11

This is a good time to use arrow functions, as they preserve the context of this.

nextStep: function() {
  this.counter += 1;
  setTimeout(() => {
    const container = this.$el.querySelector("#conversation__tram-" + this.counter);
    container.scrollTop = container.scrollHeight;
  }, 3000);

Altenatively, instead of the timeout you can use Vue.nextTick which is a more technically-correct way of doing this.

nextStep: function () {
  this.counter += 1
  this.$nextTick(() => { ... })
发布评论

评论列表(0)

  1. 暂无评论