大白话Vue源码系列(02):编译器初探
<div id="catalog"><div class="bq"> Vue 的编译器模块相对独立且简单,本篇就从这块入手,先把它干掉。 前面已经提到,Vue 项目中的 entry-runtime.js 文件是 Vue 用于构建 的源码文件,而 entry-runtime-with-compiler.js 是用于构建 的全功能文件。因此两个文件的差集必然就是编译器实现。 先看一下 entry-runtime.js 文件的内容: import Vue from './runtime/index' 文件里总共就这两行代码。这样的话就基本确定编译器相关的代码就在 entry-runtime-with-compiler.js 文件里了,事实证明也确实是这样。 entry-runtime-with-compiler.js 文件里的关键代码是为 Vue 的 prototype 扩展了一个 在具体深扒 例如下面一段 html 模板:
开发者可以通过如下操作使用 Vue 将上面这段模板编译成 render 函数: let vm = new Vue({ data: { msg: 'hello',} });
vm.$mount('#index'); console.log(vm.$options.render);
// 负责兼容多样化的输入形式并返回要处理的 html模板片段 可以看到,如果实例化 Vue 的时候同时提供了 、、 选项中的多个,则 Vue 使用的优先级是 template > el。 # 函数上面的
{ el: '#index' }
你可以传 CSS 选择器,也可以直接传 DOM, 还可以传 html 片段,怎么玩你说了算。 至此一切仍然是在扯淡,上面的都只是前戏,现在还没进入真正的编译阶段。眼贼的同学估计已经看到了,上面的 compileToFunctions 函数才是真刀实枪负责编译的。 # 函数接下来就扒进去看看
什么是抽象语法树 抽象语法树(Abstract Syntax Tree) 是源代码语法结构的抽象表示,并以树这种数据结构进行描述。AST 属编译原理范畴,有比较成熟的理论基础,因此被广泛运用在对各种程序语言(JavaScript,C,Java,Python等等)的编译处理中。Vue 同样也是使用 AST 作为中间形式完成对 html 模板的编译。 首先看一下第一步,也就是 。但是在继续 Vue 模板如何生成 AST 之前,有必要先看一下 AST 的一般解析过程。 通常程序语言解析成 AST 的过程会分为两步:
拿咱最熟悉的 JavaScript 来说吧,比如下面一段程序: let a = 1 。经过词法分析后就能得到如下一个词素列表: [ { type: 'Keyword',value: 'let' },{ type: 'Identifier',value: 'a' },{ type: 'Punctuator',value: '=' },{ type: 'Numeric',value: '1' } ] 。经过语法分析后即可得到 AST 的 JSON 格式: { type: "Program",body: [ { type: "VariableDeclaration",declarations: [ { type: "VariableDeclarator",id: { type: "Identifier",name: "a" },init: { type: "Literal",value: 1,raw: "1" } } ],kind: "let" } ],sourceType: "script" } 上面的英文单词大家不认识的自己去搜下翻译哈。JSON 是天然的树形结构,树形图想必诸位早就脑补出来了吧:
以上是使用 Esprima 工具对 JS 代码进行词法分析和语法分析的结果。 这里有一个 在线的AST生成工具。 还有一个 AST树形图预览工具。 扯了这么多,应该对抽象语法树有个模糊的概念了吧,这对理解 Vue 的 AST 构建过程就足够用了。 回到正题,Vue 的 html 模板比较特殊,因为它根本算不上是一门语言,而是基于 HTML 的声明式绑定。因此,Vue 生成的 AST 类似于大家已经非常熟悉且非常成熟的 DOM 树,实际上 Vue 也确实是仿照着 DOM 树进行解析的。只要你熟悉 DOM 树,Vue 生成的 AST 是灰常好看且简单的。如果连 DOM 树都不了解,那咱只能帮你到这里了,你一定是个假前端。 最后再次强调的一点是,Vue 编译器的编译结果是一个函数——Vue 的 render 函数,AST 只是方便处理的中间形式。 本篇完,将在下篇深究 Vue 构建 AST 的细节。
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |