之前一直不理解vue渲染过程先解析成ast之后再解析成虚拟dom是什么意思,ast和虚拟dom结构和表达的真的很像,一直觉得为什么要先解析ast,为什么不能直接变成虚拟dom。今天分享一下自己的理解,也不知道是否正确。
先说一下vue渲染过程,第一次渲染的时候要先把template解析成ast语法树,然后内部实现一个render方法进行html的字符串模板编译,接着就是通过这个render方法解析出虚拟dom,最后把虚拟dom变成真实dom。
Ast语法树,是用对象来描述原生语法。最简单的是我们原生可以通过id打印出ast语法树:
vue里面通过正则,把标签和内部的一些语法一步一步实现自己需要使用的ast,因为原生的太多了,还有之前有人评论问我HTML解析是深度优先还是广度优先,当时不能给出回答,现在觉得应该是广度优先,因为上面图片就是原生的ast语法树,是广度优先,包括dom diff算法也是。
之前有说过为什么vue要有一个且只能是一个根标签,为了方便解析,应该是由ast语法树和虚拟dom决定的。第一次渲染把template解析成语法树,其实就是render、template、el三个中的一个进行解析。
Vue内部,有了ast语法树之后,实现一个render方法,把ast变成一个字符串模板,对象和文本还要对象有三个编译方法:
_c:创建元素
_v:创建文本
_s:把对象转化成字符串,JSON.stringify变成字符串
然后通过new Function和with方法进行模板编译,有大佬说几乎所有的模板编译都要用到with。
有了render方法编译出来的模板之后,内部把这个模板方法编译之后生成虚拟dom,虚拟dom则是用对象来描述dom节点,咋一看跟ast真的很像,只是虚拟dom是自己实现的,可以更加灵活的添加和定义属性,而ast则要遵循原生的规则。
当有了虚拟dom之后,就是递归的把虚拟dom变成真实dom,然后插入到当前老节点的下面,还要把老节点删除。
Vue初始化渲染过程大概就是这样,只是内部的实现方法会复杂一些,如果是不考虑兼容写个简易的,学一学应该是能写出来,主要是思路需要好好整理。目前自己只是大概知道了一丢丢,理了理逻辑。