首页 > 解决方案 > 当 nextTick 不起作用时,如何让 Vue 从 .vue 文件中立即更新实际的 DOM?

问题描述

当我在 .vue 文件中有一个带有数据成员isLoading: false和模板的 Vue 组件时:

<div v-show="isLoading" id="hey" ref="hey">Loading...</div>
<button @click="loadIt()">Load it</button>

还有一个方法:

loadIt() {
  this.isLoading = true
  this.$nextTick(() => {
    console.log(this.$refs.hey)                  // virtual DOM
    console.log(document.getElementById('hey'))  // actual DOM
    // ...other work here
  })
}

我认为 nextTick 函数将允许虚拟和真实 DOM 更新,因此两个 console.log 行将输出相同的结果。但是,他们没有:似乎真正的 DOM 没有立即更新,因此第二个日志会产生一个元素,display: none;而第一个日志不会——我在控制台上得到了这个:

<div id="hey" data-v-964d645e="" style="">
<div id="hey" data-v-964d645e="" style="display: none;">

(顺便说一句,即使我使用setTimeout而不是this.$nextTick,我也从 console.log 中得到了相同的结果。我也尝试使用updated钩子,但在那里发生了相同的症状。如果我在 .js 文件中编写任何变体,问题就出在消失,但在 .vue 文件中仍然存在。)

Vue 如何从虚拟 DOM 更新实际 DOM 是否有某种优化或进一步的异步? 如何让实际的 DOM 立即更新?

标签: javascriptdomvue.js

解决方案


这几乎可以正常工作,消息在 DOM 更新之前和之后都匹配。

我认为您对 refs 调用返回虚拟节点而不是实际 DOM 元素的理解是不正确的。

new Vue({
  el: '#app',
  data: {
    isLoading: false
  },
  methods: {
    loadIt() {
      this.isLoading = true;
      this.tellMeAboutIt('before');
      this.$nextTick(() => this.tellMeAboutIt('after'));
    },
    tellMeAboutIt(when) {
        console.log(`Virtual ${when}:`, this.$refs.hey) // virtual DOM
        console.log(`Actual ${when}:`, document.getElementById('hey')) // actual DOM
    }
  }
});
<script src="https://unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
  <div v-show="isLoading" id="hey" ref="hey">Loading...</div>
  <button @click="loadIt()">Load it</button>
</div>


推荐阅读