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

javascript - How to get updated $refs on dynamically created component in Vue? - Stack Overflow

programmeradmin3浏览0评论

My amount of ponents depends on array quantity, so when i add new item to array, it should create new ponent.

When new ponent is created i want to get reference on it, and that's where i have a misunderstanding. Last added ponent is undefined when i try to get it.

But, if i trying to get reference on it after some time, it work. I guess it's because of asynchronous, but i'm not sure.

Why this is happening and if there a way to avoid using setTimeout?

<div id="app">
    <button @click="addNewComp">add new ponent</button>
    <new-p
        v-for="pId in arr"
        :ref="`ponents`"
        :index="pId"
        ></new-p>
    </div>
  <script type="text/x-template " id="pTemplate">
    <h1> I am a ponent {{index}}</h1>
</script>

Vueponent("newComp",{
  template:"#pTemplate",
  props:['index']
})
new Vue({
  el:"#app",
  data:{
    arr:[1,2,3,4]
  },
  methods:{
    addNewComp:function(){
      let arr = this.arr;
      let ponents = this.$refsponents;
      arr.push(arr.length+1);
      console.log("sync",ponents.length);
      console.log("sync",ponents[ponents.length-1])
      setTimeout(() => {
        console.log("async",ponents.length);
        console.log("async",ponents[ponents.length-1])
      }, 1);
    }
  }
})

codepen link

My amount of ponents depends on array quantity, so when i add new item to array, it should create new ponent.

When new ponent is created i want to get reference on it, and that's where i have a misunderstanding. Last added ponent is undefined when i try to get it.

But, if i trying to get reference on it after some time, it work. I guess it's because of asynchronous, but i'm not sure.

Why this is happening and if there a way to avoid using setTimeout?

<div id="app">
    <button @click="addNewComp">add new ponent</button>
    <new-p
        v-for="pId in arr"
        :ref="`ponents`"
        :index="pId"
        ></new-p>
    </div>
  <script type="text/x-template " id="pTemplate">
    <h1> I am a ponent {{index}}</h1>
</script>

Vue.ponent("newComp",{
  template:"#pTemplate",
  props:['index']
})
new Vue({
  el:"#app",
  data:{
    arr:[1,2,3,4]
  },
  methods:{
    addNewComp:function(){
      let arr = this.arr;
      let ponents = this.$refs.ponents;
      arr.push(arr.length+1);
      console.log("sync",ponents.length);
      console.log("sync",ponents[ponents.length-1])
      setTimeout(() => {
        console.log("async",ponents.length);
        console.log("async",ponents[ponents.length-1])
      }, 1);
    }
  }
})

codepen link

Share Improve this question asked Apr 26, 2018 at 9:55 Nazar KotsyubaNazar Kotsyuba 1771 gold badge1 silver badge12 bronze badges 2
  • I am unsure what your problem is, but maybe you're looking for the updated lifecycle? – A. L Commented Apr 26, 2018 at 10:19
  • @A.Lau yes, that helped, thank you – Nazar Kotsyuba Commented Apr 26, 2018 at 11:01
Add a ment  | 

1 Answer 1

Reset to default 12

refs, and $refs, are not reactive.

If you want to pick up the updated value, you should wait until the next render cycle updates the DOM.

Instead of setTimeout you should use Vue.nextTick():

new Vue({
  el:"#app",
  data:{
    arr:[1,2,3,4]
  },
  methods:{
    addNewComp:function(){
      let arr = this.arr;
      let ponents = this.$refs.ponents;
      arr.push(arr.length+1);
      console.log("sync",ponents.length);
      console.log("sync",ponents[ponents.length-1])
      Vue.nextTick(() => {                                         // changed here
        console.log("async",ponents.length);
        console.log("async",ponents[ponents.length-1])
      });                                                          // changed here
    }
  }
})

And this is not a "hack", this is the proper way of doing it. From the official API docs:

Vue.nextTick( [callback, context] )

  • Arguments:

    • {Function} [callback]
    • {Object} [context]
  • Usage:

    Defer the callback to be executed after the next DOM update cycle. Use it immediately after you've changed some data to wait for the DOM update.

      // modify data
      vm.msg = 'Hello'
      // DOM not updated yet
      Vue.nextTick(function () {
        // DOM updated
      })
    
      // usage as a promise (2.1.0+, see note below)
      Vue.nextTick()
        .then(function () {
          // DOM updated
        })
    
发布评论

评论列表(0)

  1. 暂无评论