首先要理解AST和VNode到底有什么区别?需要对Vue的template模板编译有一定的理解。简单来说,Vue最核心的三部分,即:compiler、reactivity、runtime。

compiler表示template编译成有规律的数据结构,即AST抽象语法树。

reactivity表示data数据可以被监控,通过proxy语法来实现。

runtime表示运行时相关功能,虚拟DOM(即:VNode)、diff算法、真实DOM操作等。

在Vue中提供了可以只采用runtime运行时就可以进行开发的模式,主要利用Vue提供的render函数来实现,代码举例如下:

render(){
    let { h } = Vue;
    return h('div',{ title : this.title , message : 'you' },[
                h('input',{ value : this.title , onInput : (ev)=>{ this.title = ev.target.value } }),
                h('button',{ onClick : this.inc },'点击')])
}
 

其中的 h 就是render函数,是可以转换成VNode的函数。可是这种方式对于使用者非常不灵活,才有了像template和JSX的应用,让编写HTML结构变得简单,即如下方式:

template : `
    <div :title="title" message="you">
        <input v-model="title">
        <button @click="inc">点击</button>
    </div>
`

我们可以发现使用template或body内的HTML,要比直接使用render函数更加直观。(注:大部分情况下模板比render方便,但也有一些情况下直接render会方便)。那么内部也是这些设计的,当有template和render同时存在的时候,优先考虑render,即内部其实就是template转换成了render函数。

而这个template模板对使用者来说是方便了很多,但是对于开发者来说,就要多一道手续,那就是如何把template转成render函数。这就是通过把template先转成AST树,然后AST树再转成render函数,render函数再转成VNode。

这样做的目的可以适配多种需求,不光是template和render的需求,还有不同平台的需求,比如AST语法树还可以针对非DOM的环境,如Weex等。

总结就是AST和VNode的职责是不同的,不能进行等价划分;即AST时compiler中把模板编译成有规律的数据结构,方便转换成render函数所存在的;而VNode是优化DOM操作的,减少频繁DOM操作的,提升DOM性能的。

扩展阅读