【问题标题】:How to get updated $refs on dynamically created component in Vue?如何在 Vue 中动态创建组件上获取更新的 $refs?
【发布时间】:2023-03-29 02:04:01
【问题描述】:

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

当创建新组件时,我想获得它的参考,这就是我误解的地方。最后添加的组件是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

【问题讨论】:

  • 我不确定您的问题是什么,但也许您正在寻找 updated 生命周期?
  • @A.Lau 是的,这有帮助,谢谢

标签: javascript vue.js


【解决方案1】:

refs 和 $refs 没有反应性。

如果你想获取更新后的值,你应该等到下一个渲染周期更新 DOM。

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

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([回调,上下文])

  • 参数:

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

【讨论】:

  • 请问有人可以在“$refs”的上下文中定义“反应式”吗?因为当可以获取对 dom/js 对象的更改时(尽管可能会稍晚一点),这难道不符合反应式的条件吗? (因为现在,“被动”似乎意味着更改会立即传达,而不是稍后传达)
  • @DamilolaOlowookere “反应式”意味着您可以在计算、监视和任何其他需要反应属性的 API 中使用它。你不能用 $refs 做任何事情。
  • @DamilolaOlowookere Reactive props 会在依赖它们的对象中触发更新,只要它发生变化。例如。 data 中的属性x 是响应式的,这意味着当它在模板中使用时,如果x 发生更改,则模板会立即重新渲染。如果存在使用x 的计算属性y,当x 发生变化时,会立即重新计算y
猜你喜欢
  • 1970-01-01
  • 2018-07-05
  • 1970-01-01
  • 2020-02-29
  • 1970-01-01
  • 2018-10-20
  • 2018-09-26
  • 2021-04-22
  • 1970-01-01
相关资源
最近更新 更多