前面我们在学习vue源码(四)手写vm.$mount方法中讲到编译函数将模板转换为渲染函数,但没有讲具体实现。这一次我们意识到了。先说模板编译的原理。一、模板编译原理概述(一)在Vue.js中创建HTML并不是创建模板的唯一方式。您可以手动编写渲染函数来创建HTML,也可以使用Vue.js中的JSX来创建HTML。(2)渲染函数是最原始的HTML创建方式。(3)模板最终会通过编译转化为渲染函数。渲染函数执行后,会得到一个vnode,用于虚拟DOM渲染。所以模板编译实际上是用虚拟DOM渲染。(4)模板编译介绍的内容是如何从虚拟DOM中获取vnode。(Template--》TemplateCompilation--》RenderingFunction(TemplateCompilation)--》vnode--》UserInterface(VirtualDOM))(5)Vue.js提供了模板语法,允许声明式地描述state和DOM之间的关系绑定它们之间的关系,然后通过模板生成真正的DOM并呈现在用户界面上。(6)在底层实现中,Vue.js会将模板编译成虚拟DOM渲染函数。当应用程序的内部状态发生变化时,Vue.js可以结合响应式系统智能地找到最少数量的组件重新渲染并执行最少数量的DOM操作。2.模板编译原理的概念(1)在使用模板时,可以使用模板中的一些变量来填充模板,也可以使用模板中的Javascript表达式,或者使用一些指令。这些特性是HTML语法所不具备的,得益于模板编译赋予了模板强大的功能。(2)模板编译的主要目标是生成渲染函数。渲染函数的作用是每次执行时,都会使用当前最新的状态生成一个新的vnode,然后使用这个vnode进行渲染。3.将模板编译成渲染函数(1)模板编译分为三部分。1.将模板解析成AST。(AbstractSyntaxTree,抽象语法树)。2.遍历AST标记静态节点。3.使用AST生成渲染函数。(2)由于静态节点并不总是需要重新渲染,因此在生成AST之后,生成渲染函数之前,需要对该节点进行一次操作,即遍历AST,标记所有静态节点,使得在虚拟DOM中更新一个节点时,如果发现该节点有这个标志,则不会重新渲染。(3)这三部分在模板编译中被抽象为三个模块,实现各自的功能,即1.Parser。2.优化器。3.代码生成器。4.Parser(1)功能:将模板解析成AST。(2)解析器内部,分为很多小的解析器,包括过滤解析器、文本解析器和HTML解析器。这些解析器然后由一条主线组装在一起。(3)在使用模板的时候,我们可以在模板中使用过滤器,过滤器解析器的作用就是解析过滤器。(4)文本解析器用于解析文本。它的主要作用是解析带有变量的文本。没有变量的文本是一段纯文本,不需要用文本解析器解析。你好{{name}}5)HTML解析器,它是解析器中的核心模块,它的作用是解析模板,每当HTML标签的开始位置、结束位置、文本或注释被解析时,就会触发Hook函数,然后通过参数传入相关信息。(6)主线上做的是监控HTML解析器。每当触发钩子函数时,都会生成相应的AST节点。在生成AST节点之前,会根据类型以不同的方式生成不同的AST。例如,如果是文本节点,则生成文本类型的AST。(7)这个AST其实有点类似于vnode,就是用Javascript中的对象来表示节点。(8)当HTML解析器解析完所有模板后,就会生成AST。5.优化器(1)目标:遍历AST,检测所有静态子树(永远不会改变的DOM节点)并标记它们。(2)AST中的静态子树标记后,每次重新渲染时,不需要为标记的静态节点创建新的虚拟节点,而是直接clone已有的虚拟节点。(3)在虚拟DOM的更新操作中,如果发现两个节点相同,正常情况下会更新这两个节点,但是如果这两个节点是静态节点,则可以直接跳过更新节点的过程。(4)优化器的主要作用是避免一些无用的工作来提高性能。因为静态节点是第一次渲染,所以不需要后续的重新渲染操作。6.代码生成器(1)模板编译的最后一步,其作用是将AST转换成渲染函数中的内容,可以称为“代码串”。
