深入浅出vue.js----模板编译原理

一、概述

(1)在Vue.js中创建HTML并不是只有模板这一种途径。既可以手动写渲染函数来创建HTML,也可以在Vue.js中使用JSX来创建HTML。

(2)渲染函数是创建HTML最原始的方法。

(3)模板最终会通过编译转换成渲染函数,渲染函数执行后,会得到一份vnode用于虚拟DOM渲染。所以模板编译其实是配合虚拟DOM进行渲染。

(4)模板编译所介绍的内容是如何让虚拟DOM拿到vnode。(模板--》模板编译--》渲染函数(模板编译)--》vnode--》用户界面(虚拟DOM))

(5)Vue.js提供了模板语法,允许声明式地描述状态和DOM之间地绑定关系,然后通过模板来生成真实DOM并将其呈现在用户界面上。

(6)在底层实现上,Vue.js会将模板编译成虚拟DOM渲染函数。当应用内部地状态发生变化时,Vue.js可以结合响应式系统,聪明地找出最小数量地组件进行重新渲染以及最少量地进行DOM操作。

二、概念

(1)平时使用模板时,可以在模板中使用一些变量来填充模板,还可以在模板中使用Javascript表达式,又或者是使用一些指令等。这些功能在HTML语法中是不存在的,这多亏了模板编译赋予了模板强大的功能。

(2)模板编译的主要目标就是生成渲染函数。而渲染函数的作用是每次执行它,它就会使用当前最新的状态生成一份新的vnode,然后使用这个vnode进行渲染。

三、将模板编译成渲染函数

(1)模板编译分三部分内容

1、将模板解析为AST。(Abstract Syntax Tree,抽象语法树)。

2、遍历AST标记静态节点。

3、使用AST生成渲染函数。

(2)由于静态节点不需要总是重新渲染,所以在生成AST之后、生成渲染函数之前这个节点,需要做一个操作,那就是遍历一遍AST,给所有静态节点做一个标记,这样在虚拟DOM中更新节点时,如果发现节点有这个标记,就不会重新渲染它。

(3)这三部分内容在模板编译中分别抽象出三个模块来实现各自的功能,分别是

1、解析器。

2、优化器。

3、代码生成器。

四、解析器

(1)作用:将模板解析成AST

(2)在解析器内部,分成了很多小解析器,其中包括过滤器解析器文本解析器HTML解析器。然后通过一条主线将这些解析器组装在一起。

(3)在使用模板时,我们可以在其中使用过滤器,而过滤器解析器的作用就是用来解析过滤器的。

(4)文本解析器就是用来解析文本的。其主要作用是用来解析带变量的文本。不带变量的文本是一段纯文本,不需要使用文本解析器来解析。

Hello {{name}}

(5)HTML解析器,它是解析器中最核心的模块,它的作用就是解析模板,每当解析到HTML标签的开始位置、结束位置、文本或则注释时,都会触发钩子函数,然后将相关信息通过参数传递进来。

(6)主线上做的事就是监听HTML解析器。每当触发钩子函数时,就生成一个对应的AST节点。生成AST节点前,会根据类型使用不同的方式生成不同的AST。例如,如果是文本节点,就生成文本类型的AST。

(7)这个AST其实和vnode有点类似,都是使用Javascript中的对象来表示节点。

(8)当HTML解析器把所有模板都解析完毕后,AST也就生成好了。

五、优化器

(1)目标:遍历AST,检测出所有静态子树(永远都不会发生变化的DOM节点)并给其打标记

(2)当AST中的静态子树被打上标记后,每次重新渲染时,就不需要为打上标记的静态节点创建新的虚拟节点,而是直接克隆已存在的虚拟节点。

(3)在虚拟DOM的更新操作中,如果发现两个是同一个节点,正常情况下会对这两个节点进行更新,但是如果这两个节点是静态节点,则可以直接跳过更新节点的流程。

(4)优化器的主要作用是避免一些无用功来提升性能。因为静态节点出了首次渲染,后续不需要任何重新渲染操作。

六、代码生成器

(1)其是模板编译的最后一步,作用是将AST转换成渲染函数中的内容,这个内容可以称为“代码字符串”。

1

生成后的代码字符串: 

with(this){ 
	return _c(
		'p',
		{
			attrs:{"title""Berwin"},
			on:{"click":c}
		},
		[_v("1")] 
	)
}

(2)这样一个代码字符串最终导出到外界使用时,会将代码字符串放到函数里,这个函数叫作渲染函数

(3)当渲染函数被导出到外界后,模板编译的任务就完成了。

const code = 'with(this){return 'Hello Berwin'}';
const hello = new Function(code);
hello();
//Hello Berwin

(4)渲染函数的作用是创建vnode。渲染函数之所以可以生成vnode,是因为代码字符串中会有很多函数调用(例如,上面生成的代码字符串中有两个函数调用_c 和 _v),这些函数是虚拟DOM提供的创建vnode的方法。

(5)vnode有很多种类型,不同类型对应不同的创建方法,所以代码字符串中的_c 和 _v其实都是创建vnode的方法,只是创建vnode的类型不同,例如_c 可以创建元素类型的vnode,而 _v可以创建文本类型的vnode。

你可能感兴趣的:(vue学习,vue,模板编译原理)