vue 源码 模板编译
- 模板编译的次要目标是将模板 (template) 转换为渲染函数(render)
模板编译作用
- Vue2.x 应用 VNode 形容视图以及各种交互,用户本人编写 VNode 比较复杂
- 用户只须要编写相似 HTML 的代码 – Vue.js 模板,通过编译器将模板转换为返回 VNode 的 render 函数
- .vue 文件会被 webpack 在构建的过程中转换成 render 函数 (外部通过 vue-loader)
- 运行时版本,vuecli 默认应用
- 构建时版本,体积大,构建速度慢
查看模板编译后果
<div id="app">
<h1>Vue<span> 模板编译 </span></h1>
<p>{{msg}}</p>
<comp></comp>
</div>
Vue.component("comp",{template:'<div>I am Comp</div>'})
const vm = new Vue({
el:"#app",
data:{msg:'Hello Compiler'},
methods:{handler(){console.log('test')
}
}
})
console.log(vm.$options.render)
获取 render 输入后果
-
with 作用是示意上面
_
的办法都是 vue 实例的办法(function anonymous() {with(this) { return _c( 'div', // tag 标签 {attrs:{"id":"app"}}, // data 用于形容 tag [ // children 形容 tag 子节点 _m(0), // 模板中的动态内容,对应下面的 h1 标签 _v(" "), // 创立空白文本,两个标签之间的空白 _c('p',[_v(_s(msg))]), // 创立 p 标签对应的 vnode,参数二是文本 _v(" "), _c('comp') ], 1 // children 拍平 ) } })
- _c() 定义在 src/core/instance/render.js (h 函数,用于创立 vnode)
- _m() / _v() / _s() 定义在 src/core/instance/render-helpers/index.js
将 html 模板转化为 render 渲染函数
- 标签内的内容,空格换行,render 会原样输入
- 去掉无异于的换行空格,可进步性能,减小内存占用
- vue3 对应的 explorer 对其做了优化,换行空格不会保留
模板编译入口
-
src/platforms/web/entry-runtime-with-compiler.js
// 把 template 转化为 render 函数 const {render, staticRenderFns} = compileToFunctions(template, { outputSourceRange: process.env.NODE_ENV !== 'production', shouldDecodeNewlines, shouldDecodeNewlinesForHref, delimiters: options.delimiters, comments: options.comments }, this)
- 此办法在 src/compiler/to-function.js 中
- 会执行 compileToFunctions 中的 compile(template,options) 开始编译
- compile 定义在 createCompilerCreator 内,会合并配置选项,调用 baseCompile(template.trim(),finalOptions)
- baseCompile 定义在 createCompiler 中,是转化的外围
-
次要做了三件事
- 把 template 转化为 ast 语法树对象
- 对 ast 对象进行 动态标记,patch 时不比照动态节点差别,间接返回,提高效率
- 把 ast 对象 转化 为 js 对象,把 js 对象 通过 createFunction 转化成匿名函数
- 解构进去,挂到 vm 实例上,编译过程完结
- ast 语法树对象入口
此时为增加完动态标记的 ast 对象
此时为转化成的 js 对象, 此时的 ast 中标记了 staticProcessed:true 示意以及解决完了
export const createCompiler = createCompilerCreator(function baseCompile (
template: string, // 模板
options: CompilerOptions // 合并之后的选项
): CompiledResult {
// 把模板转换成 ast 形象语法树
// 形象语法树用于以树的模式,形容代码构造
const ast = parse(template.trim(), options)
if (options.optimize !== false) {
// 优化形象语法树
optimize(ast, options)
}
// 把优化后的 形象语法树 转化成 字符串模式的 js 代码
const code = generate(ast, options)
// 返回 createCompiler 对象
return {
ast,
render: code.render, // 渲染函数
staticRenderFns: code.staticRenderFns // 动态渲染函数,生成动态 VNode 树
}
})
- 留神:Vue2 缩小空白换行,占内存,编译速度慢
Vue 源码 组件化
- 一个 Vue 组件,就是一个领有预约义选项的 一个 Vue 实例
- 一个组件能够组成页面上一个性能齐备的区域,组件能够蕴含脚本、款式、模板
- 组件如同积木块,领有组件如同在拼积木。每个组件外部 能够嵌套 颗粒度更小 的根本组件
- 组件化能够让咱们把页面拆分成多个可重用的组件
回顾组件注册
- 全局组件 源码 src/core/global-api/index.js
- 部分组件
- 返回了基于 组件选项对象 生成的 vue 构造函数
Vue.extend
- 把参数转化为 Vue 构造函数的子类
- 定义在 core/global-api/extend.js