1.模板编译入口

在初始化时,传入的options参数中有el属性,则进行模板渲染。其中主要的渲染函数为$mount()。//将模板挂载在HTML上
进行render判断,template判断,什么情况下,最终都是将模板转换为render函数进行渲染。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 如果有el属性 进行模板渲染
if (vm.$options.el) {
vm.$mount(vm.$options.el);
}
if (!options.render) {
// 如果存在template属性
let template = options.template;

if (!template && el) {
// 如果不存在render和template 但是存在el属性 直接将模板赋值到el所在的外层html结构(就是el本身 并不是父元素)
template = el.outerHTML;
}

// 最终需要把tempalte模板转化成render函数
if (template) {
const render = compileToFunctions(template);
options.render = render;
}
}

2.核心方法compileToFunctions

1
2
3
4
5
let ast = parse(template); //将html代码转成ast树
let code = generate(ast); //通过ast代码生成render函数
// 使用with语法改变作用域为this 之后调用render函数可以使用call改变this 方便code里面的变量取值
let renderFn = new Function(`with(this){return ${code}}`);
return renderFn

主要是通过该方法,生成ast树,根据ast树生成render函数返回


3.解析html并生成ast

使用正则表达式匹配开始和结束标签和文本解析并生成ast //通过栈来存放匹配到的标签,然后逐一处理,最后生成
### 4.根据ast重新生成代码
拿到生成好的 ast 之后 需要把 ast 转化成类似_c(‘div’,{id:”app”},_c(‘div’,undefined,_v(“hello”+_s(name)),_c(‘span’,undefined,_v(“world”))))这样的字符串 //其中也会处理指令之类的字符
### 5.code字符串生成render函数
1
2
3
4
5
6
export function compileToFunctions(template) {
let code = generate(ast);
// 使用with语法改变作用域为this 之后调用render函数可以使用call改变this 方便code里面的变量取值 比如 name值就变成了this.name
let renderFn = new Function(`with(this){return ${code}}`);
return renderFn;
}

6.小结

在Vue构造函数当中定义,初始化时调用挂载在Vue原型上的mount函数,其中核心函数是compileToFunction函数,先将template模板解析成AST树,再将AST树转化成render函数,最后根据render函数递归创建节点。