Vue 中mounted 生命周期钩子的执行时机和 v-for 的渲染顺序
1. mounted
的执行时机
mounted
是组件生命周期中DOM 挂载完成后触发的钩子,具体指:
- 组件的模板已经被编译为真实 DOM,并插入到页面中。
- 此时可以通过
this.$el
访问到组件的根 DOM 元素,也能通过document
或this.$refs
获取到已渲染的 DOM 节点。
但注意:mounted
仅保证组件自身的 DOM 结构挂载完成,并不直接等同于 “所有子元素 / 指令渲染完成”。
2. v-for
与 mounted
的关系
v-for
用于循环渲染列表,其执行逻辑是:
核心逻辑:mounted
仅与组件自身挂载相关,而 v-for
的渲染时机取决于数据源的更新时机。
- 在组件渲染阶段(
beforeMount
之后、mounted
之前),Vue 会根据v-for
的数据源(如数组)生成对应的 DOM 节点,并插入到父元素中。 - 当
mounted
触发时,v-for
循环生成的 DOM 已经存在于页面中(只要数据源在mounted
之前就已确定)。 - <template>
<div>
<p v-for="(item, index) in list" :key="index">{{ item }}</p>
</div>
</template>
<script>
export default {
data() {
return {
list: ['a', 'b', 'c'] // 初始就有数据
}
},
mounted() {
// 此时 v-for 生成的 3 个 <p> 标签已经存在于 DOM 中
console.log(this.$el.querySelectorAll('p').length) // 输出 3
}
}
</script>
此时
mounted
中可以正常获取到v-for
渲染的 DOM,因为数据源list
在组件初始化时就已确定,v-for
在mounted
前已完成渲染。3. 可能出现的 “不同步” 情况
如果
v-for
的数据源是异步获取的(如在created
中发请求),则会出现mounted
执行时v-for
尚未渲染的情况:<script>
export default {
data() {
return {
list: [] // 初始为空
}
},
created() {
// 异步获取数据(1 秒后返回)
setTimeout(() => {
this.list = ['a', 'b', 'c']
}, 1000)
},
mounted() {
// 此时 list 还是空数组,v-for 未渲染任何 DOM
console.log(this.$el.querySelectorAll('p').length) // 输出 0
}
}
</script>
原因:
mounted
在组件挂载后立即执行(约在代码运行后 0ms),而v-for
的数据源在 1000ms 后才更新,因此mounted
中无法获取到异步数据渲染的 DOM。总结
- 若
v-for
的数据源是同步数据(初始就有),mounted
执行时v-for
已经渲染完成,可直接操作 DOM。 - 若
v-for
的数据源是异步数据,mounted
执行时可能尚未渲染,需用$nextTick
或watch
确保 DOM 已更新。