如何在Vue中动态创建组件更新$ refs?

时间:2018-04-26 09:55:19

标签: javascript vue.js

我的组件数量取决于数组的数量,因此当我向数组添加新项目时,它应该创建新的组件。

当创建新组件时,我希望得到它的参考,以及我有误解的地方。 undefined。

但是,如果我在一段时间后尝试获得它的参考,它就可以了。我猜它是因为异步,但我不确定。

为什么会发生这种情况以及是否有办法避免使用setTimeout

<div id="app">
    <button @click="addNewComp">add new component</button>
    <new-comp
        v-for="compId in arr"
        :ref="`components`"
        :index="compId"
        ></new-comp>
    </div>
  <script type="text/x-template " id="compTemplate">
    <h1> I am a component {{index}}</h1>
</script>
Vue.component("newComp",{
  template:"#compTemplate",
  props:['index']
})
new Vue({
  el:"#app",
  data:{
    arr:[1,2,3,4]
  },
  methods:{
    addNewComp:function(){
      let arr = this.arr;
      let components = this.$refs.components;
      arr.push(arr.length+1);
      console.log("sync",components.length);
      console.log("sync",components[components.length-1])
      setTimeout(() => {
        console.log("async",components.length);
        console.log("async",components[components.length-1])
      }, 1);
    }
  }
})

codepen link

1 个答案:

答案 0 :(得分:2)

ref$refs不是被动的。

如果要获取更新的值,则应等到下一个渲染周期更新DOM。

而不是setTimeout,您应该使用Vue.nextTick()

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

这不是“黑客”,这是正确的做法。来自the official API docs

  

Vue.nextTick([callback,context])

     
      
  • <强>参数:

         
        
    • {Function} [callback]
    •   
    • {Object} [context]
    •   
  •   
  • <强>用法:

         

    将回调推迟到下一个DOM更新周期后执行。   在更改了一些数据以等待DOM后立即使用它   更新

    // 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
      })
    
  •