Vue异步更新DOM及$nextTick执行机制解读
在 Vue 中,DOM 更新并不是同步执行的,除非使用 this.$nextTick
方法,它可以保证在本次 DOM 更新后执行回调函数,下面我就来详细解读这个机制。
异步更新DOM
Vue 在进行 DOM 更新时,通常借助浏览器的异步更新机制,将多个数据变更合并为一次更新,以提高更新效率。这个机制体现在以下场景:
-
生命周期函数的调用是异步执行的,如
created
,mounted
等。在这些生命周期函数中,无法直接获取更新后的 DOM 元素,如果需要对 DOM 进行操作,可以使用下面介绍的$nextTick
方法。 -
Watcher 监听器的回调函数也是异步执行的。当监听的数据发生变化时,Vue 会判断是否需要触发回调函数,如果需要,它会将回调函数推入一个异步队列中,等到更新结束后再一次性执行所有回调函数。
$nextTick执行机制
在需要对更新后的 DOM 进行操作时,可以使用 $nextTick
方法。该方法接收一个回调函数作为参数,在本次 DOM 更新结束后执行该回调函数。下面介绍该方法的执行机制:
-
$nextTick
方法会将回调函数推入异步队列,并不会立即执行。 -
Vue 会在本次 DOM 更新结束后,才会遍历异步队列中的回调函数,依次执行它们。
-
如果一个回调函数在异步队列中,Vue 发现它已经存在了,则不会重复添加该函数,也不会执行两次。
下面通过两个示例来说明异步更新和 $nextTick
的机制。
示例一
在以下代码中,组件的一个数据属性 count
被改变时,我们需要得到更新后的 DOM 元素的高度。因为 DOM 更新是异步执行的,所以直接获取元素的高度是不准确的。我们可以在更新后使用 $nextTick
方法获取正确的高度值。
<template>
<div class="container">
<div ref="content" :style="{ height: height + 'px' }">
<p v-for="i in count" :key="i">{{ i }}</p>
</div>
</div>
</template>
<script>
export default {
data() {
return {
count: 0,
height: 0
};
},
methods: {
handleClick() {
this.count++;
this.$nextTick(() => {
this.height = this.$refs.content.clientHeight;
});
}
},
mounted() {
this.height = this.$refs.content.clientHeight;
}
};
</script>
在组件 mounted
阶段,我们通过 ref
获取容器元素的高度并赋值给 height
属性。在 handleClick
方法中,改变了 count
值后,调用 $nextTick
方法等待 DOM 更新后获取新的高度值。在回调函数中,我们通过 $refs
获取容器元素并获取它的 clientHeight
属性,赋给 height
,此时,更新后的高度值已经被正确获取。
示例二
在以下代码中,当用户在搜索框中输入文字时,我们需要更新列表数据项以匹配搜索词,并更新搜索框提示的文字。然而搜索框的内容是双向绑定的,所以在更新列表数据后,需要使用 $nextTick
等待更新后 DOM 元素的渲染,才能更新搜索框提示的文字。
<template>
<div class="container">
<input v-model="keyword" @input="handleSearch" />
<ul>
<li v-for="item in filteredList" :key="item.id">{{ item.name }}</li>
</ul>
<div>{{ message }}</div>
</div>
</template>
<script>
export default {
data() {
return {
keyword: "",
list: [
{ id: 1, name: "apple" },
{ id: 2, name: "banana" },
{ id: 3, name: "carrot" }
],
message: ""
};
},
computed: {
filteredList() {
return this.list.filter(item =>
item.name.toLowerCase().includes(this.keyword.toLowerCase())
);
}
},
methods: {
handleSearch() {
this.$nextTick(() => {
this.message = `共搜索到 ${this.filteredList.length} 个结果`;
});
}
}
};
</script>
在上述示例中,搜索框的值是双向绑定的,当用户在输入框中输入文字时,会触发 handleSearch
方法,在该方法中,我们首先使用 this.$nextTick
方法等待 DOM 的更新,之后使用 computed
属性过滤数据列表,再通过 $nextTick
方法获取更新后的列表项数量,并赋值给 message
,完成搜索结果的提示。
至此,Vue 异步更新DOM及 $nextTick
执行机制的解读就讲解完了。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Vue异步更新DOM及$nextTick执行机制解读 - Python技术站