Vue 模板编译-概述
-
模板编译的作用?
- Vue2.0 使用 vnode 描述视图以及各种交互,用户自己编写 vnode 比较复杂
- 模板编译可以让用户只需要编写类似 HTML 的代码 - Vue.js 模板,通过编译器将模板转换为返回 vnode 的 render 函数
- .vue 文件会被 webpack 在构建的过程中转换为 render 函数
运行时编译的前提必须是使用完整版的 Vue,它会再运行时把模板转换成 render 函数。因为多了编译器的代码,使得 Vue 的体积变大,运行的速度也会相应的变慢。Vue-cli 创建的项目默认使用的运行时版本的 Vue。
模板编译的结果
在 src/platforms/web/entry-runtime-with-compiler.js 中定义了 Vue.$mount, 在这个方法中首先会判断是否传入了 render 函数,如果没有传入 render 函数,判断是否传入了 template ,如果没有传入 template 就会把 el 的 outerHTML 作为 template 。
获取到 template 之后会调用 compileToFunctions 这个方法将 template 转换成 render 函数。
一个编译生成的 render 函数
(ƒunction anonymous() {
with (this) {
return _c(
'div',
{ attrs: { "id": "app" } },
[
_m(0),
_v(" "),
_c('p', [_v(_s(msg))]),
_v(" "),
_c('comp', { on: { "myclick": handler } })
],
1
);
}
});
可以看到在 render 函数中就是调用了 Vue 中挂载的下划线开头的方法来生成 vnode
- _c()
- src/core/instance/render.js
- _m()/_v()/_s()
- src/core/instance/render-helpers/index.js
// 对编译生成的 render 进行渲染的方法
vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false)
_m()/_v()/_s() 这几个成员是在 Vue 的实例成员初始化的 renderMixin 中调用 installRenderHelpers 方法给实例挂载的用于生成 vnode 的实例方法。
export function renderMixin (Vue: Class<Component>) {
// install runtime convenience helpers
installRenderHelpers(Vue.prototype)
}
installRenderHelpers 方法如下
export function installRenderHelpers (target: any) {
target._o = markOnce
target._n = toNumber
target._s = toString // toString 函数
target._l = renderList
target._t = renderSlot
target._q = looseEqual
target._i = looseIndexOf
target._m = renderStatic // 处理静态内容
target._f = resolveFilter
target._k = checkKeyCodes
target._b = bindObjectProps
target._v = createTextVNode // 创建文本 vnode 节点
target._e = createEmptyVNode
target._u = resolveScopedSlots
target._g = bindObjectListeners
target._d = bindDynamicKeys
target._p = prependModifier
}
- _v
export function createTextVNode (val: string | number) {
return new VNode(undefined, undefined, undefined, String(val))
}
- _s
/**
* Convert a value to a string that is actually rendered.
*/
export function toString (val: any): string {
return val == null
? ''
: Array.isArray(val) || (isPlainObject(val) && val.toString === _toString)
? JSON.stringify(val, null, 2)
: String(val)
}
- render 函数分析
render 函数的核心是调用 _c 这个方法也就是 _createElement() 生成并返回 vnode。
上述 render 函数对应的 template
<div id="app">
<h1>Vue<span>模板编译过程</span></h1>
<p>{{ msg }}</p>
<comp @myclick="handler"></comp>
</div>
_c 中的参数
- “div” 是标签名
- { attrs: { “id”: “app” } }, 是标签属性
- 下一个数组是 children
- boolean 是处理 children 的方法,如果传1,就是将 children 拍平,如果 children 是多维数组转换成一维数组。
children 的处理
_m(0)处理静态内容_v(" ")创建一个空白vnode文本节点_c('p', [_v(_s(msg))])创建 p 标签_c('comp', { on: { "myclick": handler } })创建组件
可以使用 Vue Template Explorer 这个工具来分析 template 对应的 render 函数
- https://template-explorer.vuejs.org/
- https://vue-next-template-explorer.netlify.app/
2699

被折叠的 条评论
为什么被折叠?



