我最近一直在研究Vue的nextTick,我自己写了下面的演示代码:
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
const vue = new Vue({
el: '#root',
template: '<div><div id="dom">{{msg}}</div><button @click="add">add</button></div>',
data() {
return {
msg: 1
}
},
watch: {
msg(value) {
console.log('msg>>>>>', value);
}
},
methods: {
add() {
const dom = document.getElementById('dom');
dom.textContent = '30'
for(let i = 0; i < 3; i ++) {
this.msg ++
}
this.$nextTick(() => {
console.log('msg.content2>>>>>>', dom.textContent)
})
}
}
})
</script>
</html>
liveDemo:jsfiddle
结果真的让我很困惑。正如我所料,点击添加按钮后,dom.textContent = '30'
将dom元素的textConent更改为30。下一个for循环,将msg
添加为4,因为Vue将异步更新页面,我们无法在页面中看到最新的结果。在this.$nextTick
之后,Vue将使用更新后的msg
立即重新渲染dom元素,我们知道现在是4。所以dom元素的textContent现在应该是4,但它仍然是30。为什么会发生这种情况?我错在哪里?
1条答案
按热度按时间bhmjp9jg1#
我想我知道是怎么回事了
当执行
dom.textContent = '30'
时,它将元素的文本内容更改为'30'。但它并不像我之前想的那样,直接将
dom
元素的Text子节点的textContent修改为新的内容,而是生成一个新的Text
子节点,并替换原来的子节点。稍后,在
$nextTick
函数中,Vue使用最新的msg
值(现在为4)来更新Text
节点的内容。然而,Vue现在使用的Text
节点是存储在el
属性中的旧节点,而不是更新后的dom元素的Text
子节点。因此,这种更改是无用的。页面和console.log语句都无法显示预期结果。在将演示代码更改为以下版本后,我终于得到了我想要的:
live demo
另一个demo:
change div's textContent creates a new Text node