# 模版编译
# 模版渲染过程
vue template complier,将模版编译为render函数(利用with函数),执行render函数生成vnode。 模版不是html 有指令 插值 js表达式 能实现判断 循环
模版通过compile 生成AST,AST通过render编译生成 VNode代码片段。 基于VNode我们执行patch和diff。
const compiler = require('vue-template-compiler');
//template模版
const template = `
<p id="container">
<span v-if="flag === 'a' ">A</span>
<span v-else>B</span>
</p>
`;
//模版编译生成AST
const res = compiler.compile(template);
console.log(res);
{
ast: {
type: 1,
tag: 'p',
attrsList: [ [Object] ],
attrsMap: { id: 'container' },
rawAttrsMap: {},
parent: undefined,
children: [ [Object] ],
plain: false,
attrs: [ [Object] ],
static: false,
staticRoot: false
},
render: `with(this){return _c('p',{attrs:{"id":"container"}},[(flag === 'a' )?_c('span',[_v("A")]):_c('span',[_v("B")])])}`,
staticRenderFns: [],
errors: [],
tips: []
}
//AST通过render生成VNode
console.log(res.render())
//生成的with函数return一个 _c函数,就是createElement。执行函数体返回VNode。
//with(this){return _c('p',{attrs:{"id":"container"}},[(flag === 'a' )?_c('span',[_v("A")]):_c('span',[_v("B")])])}
我们通过 vue-template-compiler,可以将template转换成with函数的VNode。但是在实际开发环境中,我们通过webpack打包经过vue-loader处理之后,生成的dist文件就已经是一段段的编译好的with函数了。
# 直接写render函数
vue中可以通过直接写render函数,取代template。 React使用jsx语法糖,直接使用render,没有template。
Vue.component('Hello',{
render:function (createElement){
return createElement(
'h'+this.level,
[
createElement('a',{
attr:{
name:'head',
href:'#'
}
},'this is link')
]
)
}
})
# 渲染过程
- 1 解析template为render函数(或在开发环境已经完成,vue-loader。正常单页webpack打包通过vue-loader,就已经变成了render函数)
- 2 触发响应式,observe的过程。
- 3 执行render函数,生成vnode,patch(elem,vnode)
# 更新过程
- 修改data,触发setter
- 重新执行render函数,生成 newVnode
- patch(VNode,newVVode)