DOM在mounted钩子被调用时才真正挂载完成;渲染优先级为render > template > el,决定视图内容来源,且该顺序在初始化阶段即确定不可覆盖。

Vue 组件的渲染优先级和 DOM 挂载时机是两个紧密关联但不同层面的问题:前者决定“用什么内容生成视图”,后者回答“什么时候真实 DOM 可用”。关键结论很直接——DOM 在 mounted 钩子被调用时才真正挂载完成;而模板/渲染函数的优先级决定了 Vue 用哪一部分代码来构建这个 DOM。
渲染入口的优先级顺序:render > template > el
Vue 渲染视图时,会按固定优先级选择内容来源:
- render 函数优先级最高。它直接返回虚拟节点(VNode),跳过模板编译,适合复杂逻辑或 JSX 场景。
- template 选项次之。Vue 将其编译为 render 函数,再生成 VNode;若同时写了 render 和 template,template 会被忽略。
- el 所指 DOM 的 innerHTML最低。仅当前两者都未提供时,Vue 才提取 el 元素的 HTML 字符串作为模板源(注意:不是 outerHTML,而是其内部结构)。
这个顺序在组件初始化阶段就已确定,且不可覆盖。例如:el: '#app' 和 template: '<p>{{ msg }}</p>' 同时存在时,el 内容会被 template 替代;若再加 render() { return h('p', this.msg) },则 template 和 el 都失效。
DOM 挂载完成的明确节点:mounted 钩子
DOM 真实插入文档并可被 JS 访问,发生在 mounted 生命周期钩子中:
立即学习“前端免费学习笔记(深入)”;
-
beforeMount时,虚拟 DOM 已生成,但尚未挂载到真实 DOM —— 此时this.$el存在,但里面还是旧内容或空节点。 -
mounted被调用,代表 Vue 已把首次渲染的 DOM 片段(由 render/template/el 生成)正式插入页面,this.$el此时包含完整、响应式绑定后的节点,可安全执行querySelector、getBoundingClientRect或第三方库初始化(如 Chart.js、Map 实例)。 - 常见误区:在
created中操作 DOM 会失败,因为此时$el还未创建;nextTick可延后到 DOM 更新后,但它不等于挂载完成——只保证“本次更新已生效”,而 mounted 是“首次挂载已完成”的唯一可靠标志。
父子组件的挂载节奏:子先 mount,父后 finish
当组件有嵌套关系时,挂载不是同步完成的:
- 父组件执行
beforeMount→mounted前,其所有子组件会依次走完自己的beforeMount→mounted。 - 也就是说,父组件的
mounted总是最后一个触发,此时全部子组件 DOM 已就位。若需在父组件中操作某个子组件的 DOM,必须等父mounted;若子组件需访问父 DOM,应确保父已挂载(比如用onMounted+nextTick或监听父 ref 变化)。 - 这个顺序也解释了为什么在父
mounted里能拿到子组件的ref对应的真实元素,而在父created或beforeMount中拿不到。
实际开发中的典型用法
结合优先级与挂载时机,日常写法更清晰:
- 需要动态生成结构?写
render函数,它最灵活、性能最优,且天然支持条件逻辑和递归。 - 只是替换局部模板?用
template更直观,配合v-if/v-for足够表达多数 UI。 - 快速原型或服务端渲染 fallback?依赖
el最省事,但注意它无法响应数据变化(静态 HTML)。 - 所有 DOM 相关操作(尺寸测量、第三方插件初始化、焦点设置)统一放在
mounted;异步数据请求可放created(早发起)或mounted(需 DOM 配合),按需选择。


















