??(三)complier模板编译-vue源码动手写系列
2020/2/28 11:15:37
本文主要是介绍??(三)complier模板编译-vue源码动手写系列,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
在上一篇文章,我们介绍了虚拟Dom的内容,创建vnode需要调用createElement去生成,但是在日常的开发当中,我们很少去写一堆复杂的createElement
代码去描述页面,在Vue中通常是写一个template模板,而最终我们会把这个模板编译成一个渲染函数,用这个渲染函数去生成vnode,这个过程就是模板编译的过程,通常由webpack vue-loader
完成,当然你也可以引入Vue的runtime + compiler
版本,在运行时才去编译,但是一般不推荐这样做,除非你确实有项目运行期间编译模板的需求,不然都是选择一个不带编译器的vue版本去减少代码体积。
模板编译的过程到底干了什么到现在你可能还不是很清楚,这里简单放一段伪代码去说明一下总体的编译流程吧,现在我们有一个这样的模板:
<div> <p>{{name}}</p> </div> 复制代码
1️⃣首先第一步,编译器会去进行一些词法分析,逐段字符串去解析,最终生成一个抽象语法树(AST)
:
{ tag: "div" type: 1, staticRoot: false, static: false, plain: true, parent: undefined, attrsList: [], attrsMap: {}, children: [ { tag: "p" type: 1, staticRoot: false, static: false, plain: true, parent: {tag: "div", ...}, attrsList: [], attrsMap: {}, children: [{ type: 2, text: "{{name}}", static: false, expression: "_s(name)" }] } ] } 复制代码
2️⃣第二步主要是一些优化工作,它会去编译我们生成的AST
,然后标记一下静态节点和静态根节点。
static: true, staticRoot: false 复制代码
3️⃣第三步是代码字符串生成,它同样会去遍历这个AST
,然后根据节点的类型去调用不同的vnode生成方法如createElement
,createTextNode
去拼接渲染函数,下面最终生成的结果,其中_c
, _v
是createElement
,createTextNode
的简写,_s
暂时可以理解为增加版的toString方法。
`with(this)(return _c('div', [_c('p', [_v(_s(name))])]))` 复制代码
所以编译的流程可以划分为三大模块,对应vue源码中的parse
,optimize
,generate
三个方法:
- 解析器
- 优化器
- 代码生成器
到这里我们只需要对它们有一个总体认识即可,下面的篇幅将会对每个模块的原理详细的分析,文章通读过后再回来看看总体的流程就会非常清晰了。
解析器(parse)
1️⃣HTML 解析器
解析器的作用就是把模板解析成抽象语法树AST,入口是一个parseHTML
方法,方法里面会有一个while
循环,这个循环会通过一些正则去截取模板中的内容,根据匹配到内容的不同再去调用钩子函数去生成不同类型的AST树的节点,包括start
,end
,chars
,comment
, 这几个钩子分别处理开始标签
、结束标签
、文本
、注释
,过程中会不断截取一小段字符串,待整个模板html都被清空后模板才解析完成,看下面的伪代码:
function parseHTML(html, options) { while(html) { if (匹配到开始标签) { options.start(tag, attrs, unary) continue } if (匹配到结束标签) { options.end() continue } if (匹配到文本) { options.chars(text) continue } if (匹配到注释) { options.start(text) continue } } } 复制代码
parseHTML(template, { start(tag, attrs, unary) { // 每当解析到标签的开始位置时,触发该函数 }, end() { // 每当解析到标签的结束位置时,触发该函数 }, chars(text) { // 每当解析到文本时,触发该函数 }, comment(text) { // 每当解析到注释时,触发该函数 } }) 复制代码
为了方便理解,这里再手动模拟一下HTML解析器的运行过程,首先我们有一个模板内容:
<div> <p>{{name}}</p> </div> 复制代码
最初的模板:
`<div> <p>{{name}}</p> </div>` 复制代码
第一次循环时,截取一小段字符串<div>
,并且触发钩子函数start
,截取后模板剩下:
` <p>{{name}}</p> </div>` 复制代码
第二次循环,截取了一段换行内容:
这篇关于??(三)complier模板编译-vue源码动手写系列的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-10-04package.json 文件位置在哪?-icode9专业技术文章分享
- 2024-10-01Craco.js学习:从入门到实践指南
- 2024-10-01Create-React-App学习:入门与实践指南
- 2024-10-01CSS-in-JS学习:从入门到实践指南
- 2024-09-30JSX语法学习:从入门到初步掌握
- 2024-09-30Mock.js学习:入门教程与实战演练
- 2024-09-30React Hooks学习:从入门到实践
- 2024-09-30受控组件学习:React中的基础入门教程
- 2024-09-29JS定时器教程:初学者必看指南
- 2024-09-29JS对象教程:初学者的全面指南