Vue源码 模板编译解析
vue源码 模板编译
- 模板编译的主要目的是将模板(template)转换为渲染函数(render)
- Vue2.x使用VNode描述视图以及各种交互,用户自己编写VNode 比较复杂
- 用户只需要编写类似 HTML的代码 - Vue.js模板,通过编译器将模板转换为返回 VNode 的 render函数
- .vue文件会被webpack在构建的过程中转换成 render函数 (内部通过vue-loader)
- 运行时版本,vuecli默认使用
- 构建时版本,体积大,构建速度慢
Vue模板编译{{msg}}
Vue.component("comp",{
template:'I am Comp'
})
const vm = newVue({
el:"#app",
data:{
msg:'Hello Compiler'
},
methods:{
handler(){
console.log('test')
}
}
})
console.log(vm.$options.render)
【Vue源码 模板编译解析】获取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
- 标签内的内容,空格换行,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语法树对象入口
文章图片
此时为转化成的 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 实例
- 一个组件可以组成页面上一个功能完备的区域,组件可以包含脚本、样式、模板
- 组件好像积木块,拥有组件好像在拼积木。每个组件内部 可以嵌套 颗粒度更小 的基本组件
- 组件化可以让我们把页面拆分成多个可重用的组件
- 全局组件 源码src/core/global-api/index.js
- 局部组件
- 返回了基于 组件选项对象 生成的 vue构造函数
- 把参数转化为Vue构造函数的子类
- 定义在 core/global-api/extend.js
推荐阅读
- vue-cli|vue-cli 3.x vue.config.js 配置
- 2020-04-07vue中Axios的封装和API接口的管理
- opencv|opencv C++模板匹配的简单实现
- Android事件传递源码分析
- VueX--VUE核心插件
- Quartz|Quartz 源码解析(四) —— QuartzScheduler和Listener事件监听
- web网页模板|如此优秀的JS轮播图,写完老师都沉默了
- [源码解析]|[源码解析] NVIDIA HugeCTR,GPU版本参数服务器---(3)
- ffmpeg源码分析01(结构体)
- Java程序员阅读源码的小技巧,原来大牛都是这样读的,赶紧看看!