Vue 模板编译:HTML 是怎么变成 JS 的?

📅 2026/6/30 5:47:45
Vue 模板编译:HTML 是怎么变成 JS 的?
你写的模板浏览器不认识用 Vue 写代码的时候你一定写过这样的模板template div idapp p{{ message }}/p button clickhandleClick点击/button /div /template看起来很直观。但问题是——浏览器不认识这玩意儿。{{ message }}不是 HTML 标准click也不是合法属性。你写的是Vue 方言Vue 必须把它翻译成浏览器能跑的纯 JavaScript翻译结果大概长这样function render() { return h(div, { attrs: { id: app } }, [ h(p, {}, [this.message]), h(button, { on: { click: this.handleClick } }, [点击]) ]) }从div{{ message }}/div到h(div, {}, [this.message])—— 这个过程就叫模板编译。h()是 Vue 创建虚拟 DOM 节点的方法h(div, { id: app }, children)相当于创建一个 div 元素id 为 app。一个比喻翻译家模板编译就像一个翻译家把HTML 方言翻译成JavaScript 母语模板HTML 方言 渲染函数JS 母语 ┌──────────────────────┐ ┌──────────────────────┐ │ div classbox │ │ h(div, │ │ {{ msg }} │ ──》 │ { class: box }, │ │ /div │ │ [this.msg]) │ └──────────────────────┘ └──────────────────────┘和你用翻译软件把中文翻成英文一样——换了一种语言意思不变。三大步骤翻译不是一步到位的分三步走模板字符串 │ ▼ ┌─────────┐ │ Parse │ 把字符串变成 AST抽象语法树 │ 解析 │ 就像把汉语句子拆成主谓宾 └────┬────┘ │ ▼ ┌─────────┐ │ Optimize│ 标记静态节点——不会变的部分标出来 │ 优化 │ 省得每次重新创建白费力气 └────┬────┘ │ ▼ ┌─────────┐ │ Generate│ 把 AST 变成代码字符串 │ 生成 │ 最终输出 render 函数 └────┬────┘ │ ▼ function render() { return h(...) }用一个生活比喻来记步骤类比输入输出Parse把一段中文拆成主谓宾定状补HTML 字符串AST 语法树Optimize标出文中固定搭配不用每次查词典AST带静态标记的 ASTGenerate把中文句子翻译成英文优化后的 ASTfunction render() { ... }编译发生在什么时候1. 构建时编译主流在用 webpack vue-loader 或 Vite 打包时.vue文件里的template在打包阶段就被编译成了 render 函数。开发时 打包后发给用户 ┌────────────┐ ┌──────────────┐ │ .vue 文件 │ ──》 │ 纯 JS 代码 │ │ template │ 编译 │ render 函数 │ │ script │ │ 不包含编译器 │ │ style │ └──────────────┘ └────────────┘好处用户下载的代码不含编译器编译器本身不小体积更小页面打开更快。2. 运行时编译直接在浏览器里引入 Vue模板写在 HTML 中Vue 初始化时现场编译div idapp p{{ message }}/p !-- 浏览器里当场编译 -- /div好处不用构建工具写好就能跑。代价需要引入完整版 Vue含编译器体积大不少。绝大多数项目都用构建时编译运行时编译只适合快速写 demo 的场景。