Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue的编译过程:template、AST、Render过程 #5

Open
terribleness opened this issue Mar 10, 2018 · 0 comments
Open

Vue的编译过程:template、AST、Render过程 #5

terribleness opened this issue Mar 10, 2018 · 0 comments

Comments

@terribleness
Copy link
Owner

terribleness commented Mar 10, 2018

第三节Vue双向数据绑定:Observe、Watcher、Depd的关系”,关键是Object.defineProperty的set和get方法构造了订阅-发布模型。其中属性set方法的是在data、props、watch、computed等中赋值时发布更新,get方法是在编译template模板生成render函数后自动调用了get方法产生订阅watcher。

那么template模板是如何编译成render函数的呢?

这一节我们主要分析Vue中编译过程:template、AST(抽象语法树)、render过程。
我们看到源代码中’instance/init.js’文件中,如下:
image

这个_init函数已经出现很多次了,我们上一篇文章,主要是分析了其中initState(vm)方法中如何构建双向数据绑定的,而Vue中的编译过程我们主要是看到最后一句 wm.$mount(vm.$options.el),在第一篇文章中,Vue扩展实例方法我们提到过Vue.prototype.$mount,在’runtime/index.js’文件中,如下:
image

那么如果编译过的template就会调用这个$mount函数去渲染页面,但是如果没有编译过的template呢,我们需要先看到’web/entry-runtime-with-compiler.js’文件,这里面会先去做template编译过程再调用$mount函数,如下:
image

第一个红框是先保存之前的$mount函数,也就是在’runtime/index.js’中定义的Vue.prototype.$mount函数,第三个红框是使用这个保存下来的mount函数继续执行,那么第二个红框就是我们这节需要分析的重点了,这就是Vue的编译过程。
我们进入到compileToFunctions函数中,如下:
image

再进入createCompiler中,如下:
image

这个createCompiler是createCompilerCreator函数的返回值,但是参数是一个baseCompile函数。进入createCompilerCreator函数中。
image

我们看到createCompilerCreator返回了一个createCompiler函数。这里有点绕,但是思路清晰一点,实际上是上上图中 function baseCompile函数实际在做编译工作,参数是vue的实例化的参数options,而上图中createCompiler函数中前一部分实际上是对options参数做了一个替换工作。所以实际编译工作看到baseCompile(template,finalOptions)这句话,对了这里要插入一句template的来历,因为一些面试题中提到,Vue实例化过程中,el属性和template和render都有内容时,实际渲染的html是以哪个为准?这个问题我们看到’entry-runtime-with-compiler.js’这个文件,$mount函数部分如下:
image

这段话的目的就是去确认template实际内容时以el、template、render函数中哪一个为准?
1、首先判断render函数是否存在,如果存在则以render函数为准,直接渲染
2、如果render函数不存在,则检查template模板是否存在,如果存在template则编译template模板成为render函数
3、如果template不存在,则取得el标签中innerHTML作为template模板,再生成render函数
4、如果el不存在,则生成一个空的div标签。

言归正传,我们回到baseCompile函数中,看编译template成render函数过程。
image

函数第一句const ast = parse(template.trim(),options)是生成抽象语法书,比如例子:
image

生成的AST如下:
image

第二句是optimize(ast,options)优化AST树
第三句是const code = generate(ast, options)这一句之后,生成render函数了如下:
image

过程就是这样,生成的render函数继续执行后面的工作,我们具体来看看这三句代码的内容。
image

parse(template.trim(),options)

待续。。

optimize(ast,options)

待续。。

const code = generate(ast, options)

待续。。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant