「这是我参与2022首次更文挑战的第23天,活动详情查看:2022首次更文挑战」
模板编译
本章呢,还是我最喜欢的炒冷饭环节,通过Vue中的源码,学习模板编译的过程
模板编译的主要目的
- 模板编译的主要目的是将模板 (
template) 转换为渲染函数 (render)
<div>
<h1 @click="handler">title</h1>
<p>some content</p>
</div>
- 渲染函数
render
render (h) {
return h('div', [
h('h1', { on: { click: this.handler} }, 'title'),
h('p', 'some content')
])
}
这就是上面的html变成render函数的效果啦!
模板编译的作用
-
Vue 2.x 使用
VNode描述视图以及各种交互,用户自己编写VNode比较复杂 -
用户只需要编写类似
HTML的代码(它的本质就是Vue模板 ),通过编译器将模板转换为返回VNode的render函数 -
.vue文件会被webpack在构建的过程中转换成render函数,webpack本身是不支持把模板编译成render函数的,它本身是通过vue-loader来实现这一步操作的
体验模板编译的结果
-
带编译器版本的 Vue.js 中,使用 template 或 el 的方式设置模板
<div id="app"> <h1>Vue<span>模板编译过程</span></h1> <p>{{ msg }}</p> <comp @myclick="handler"></comp> </div> <script src="../../dist/vue.js"></script> <script> Vue.component('comp', { template: '<div>I am a comp</div>' }) const vm = new Vue({ el: '#app', data: { msg: 'Hello compiler' }, methods: { handler () { console.log('test') } } }) console.log(vm.$options.render) </script> -
编译后 render 输出的结果
(function anonymous() { with (this) { return _c( "div", { attrs: { id: "app" } }, [ _m(0), // 用来处理静态内容 _v(" "), // 创建一个空白的文本节点 _c("p", [_v(_s(msg))]), // createElement; `_s` 是调用 toString函数 _v(" "), _c("comp", { on: { myclick: handler } }), // 创建自定义组件的VNode ], 1 ); } }); -
_c是createElement()方法,定义的位置instance/render.js中 -
相关的渲染函数(_开头的方法定义),在
instance/render-helps/index.js中// instance/render-helps/index.js target._v = createTextVNode target._m = renderStatic // core/vdom/vnode.js export function createTextVNode(val: string | number) { return new VNode(undefined, undefined, undefined, String(val)) } // 在 instance/render-helps/render-static.js export function renderStatic(index: number, isInFor: boolean): VNode | Array<VNode> { const cached = this._staticTrees || (this._staticTrees = []) let tree = cached[index] // 如果已经渲染了静态树并且不在 v-for 中, // 我们可以重用同一棵树。 if (tree && !isInFor) { return tree } // 否则,渲染一棵新鲜的树。 tree = cached[index] = this.$options.staticRenderFns[index].call( this._renderProxy, null, this // 为功能组件模板生成的渲染 fns ) markStatic(tree, `__static__${index}`, false) return tree } -
把
template转换成render的入口src\platforms\web\entry-runtime-with-compiler.js
Vue Template Explorer
我们可以通过下面两个网页工具来学习render函数,也可以用这个工具 对 Vue2.X 和 Vue3.X 的 render 函数进行比对,可以发现两个版本的模板编译差别(说不定到时候就是面试加分项哦!)
小结
模板编译的过程用三个词来说
- 解析:解析器将模板解析为抽象语树 AST,只有将模板解析成 AST 后,才能基于它做优化或者生成代码字符串
- 优化:优化抽象语法树,检测子节点中是否是纯静态节点
- 生成 很简单的总结,但是里面的东西却非常的多,下个小结我们会仔细进行详细解析的,希望大家可以多多学习啦!
关注!收藏!点赞! 求求啦!你的每一个点赞都是我更新的动力!