当我在.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和实际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?
答案 0 :(得分:1)
请查看文档中的Vue lifecycle。值得注意的是,这两个事件之间存在脱节。另外请注意,nextTick()
等待下一个DOM更新周期,而不必等待虚拟DOM。
通常通过使用updated
生命周期挂钩来解决此问题,该挂钩在虚拟DOM已更新后在之后执行代码。如果您需要执行某些代码以确保虚拟DOM已被更新,则可以在此进行。
您可能也对reactivity in depth感兴趣。这应该是生命周期图的很好补充。
答案 1 :(得分:1)
这几乎可以按预期工作,并且在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>
答案 2 :(得分:0)
结果证明,eslint-loader缓存或babel-loader缓存出现问题导致了这种怪异。我只能通过删除所有node_modules\.cache
来解决此问题。太糟糕了,我不知道为什么会首先发生。