前言React和Vue都使用了虚拟DOM。如何在Vue中使用它?Vue中模板转换成真实DOM的思路Vue中模板的编译是这样的过程:模板--->ast(抽象树)->render函数->虚拟dom->实际dom。vue中的模板被编译器编译成ast(用来表示模板的js对象,也可以说ast是用来表示源码的js对象),然后将ast生成成相应的renderfunction(这里先不说ast的转换Details),render函数然后生成虚拟节点vnode(用来描述节点及其子节点的信息),vnodes的集合构成了VirtualDom(整个vnodevue组件构建的树称为虚拟Dom树),最终生成真实的Dom。Vue中的模板转化为虚拟DOM细节ast的结构。ast是表示源代码的js对象(描述dom结构的js对象)。ast格式:functionadd(a,b){returna+//有什么奇怪的东西混合进来了b}转换成ast后:FunctionDeclaration{type:'FunctionDeclaration',id:Identifier{type:'Identifier',name:'add',loc:{start:[Object],end:[Object],lines:[Lines],tokens:[Array],indent:2}},params:[标识符{type:'Identifier',name:'a',loc:[Object]},标识符{type:'Identifier',name:'b',loc:[Object]}],body:BlockStatement{type:'BlockStatement',body:[[ReturnStatement]],loc:{开始:[对象],结束:[对象],行:[行],标记:[数组],缩进:2}},生成器:false,表达式:false,async:false,loc:{开始:{行:2,列:2,令牌:0},结束:{行:6,列:3,令牌:13},行:行{信息:[数组],映射:[],cachedSourceMap:null,cachedTabWidth:undefined,length:7,name:null},tokens:[[对象],[对象],[对象],[对象],[对象],[对象],[对象],[对象],[对象],[对象],[对象],[对象],[Object]],indent:2}}ast转换成渲染函数vue模板如下:
{{blogTitle}}
最终会转换成如下渲染函数:render:function(createElement){returncreateElement('h1',this.blogTitle)}createElementfunctionparameters:createElement(//{String|Object|Function}//一个HTML标签名称,组件选项对象,或者//一个解析任何上面必须填写。'div',//{Object}//模板中属性对应的数据对象,可选。{//(详见下一节)},//{String|Array}//子虚拟节点(VNodes),由`createElement()`构造,//也可以使用字符串生成“文本虚拟节点”。可选。['先写一些文字',createElement('h1','aheadline'),createElement(MyComponent,{props:{someProp:'foobar'}})])createElement的第二个参数是节点的属性:{//与`v-bind:class`相同的API,//接受字符串、对象或字符串和对象数组'class':{foo:true,bar:false},//与`v-相同bind:style`的API相同,//接受字符串、对象或对象数组style:{color:'red',fontSize:'14px'},//常见的HTML特性attrs:{id:'foo'},//组件道具props:{myProp:'bar'},//DOM属性domProps:{innerHTML:'baz'},//事件侦听器位于`on`属性中,//但不再支持装饰器,如`v-on:keyup.enter`。//需要在处理函数中手动检查keyCode。on:{click:this.clickHandler},//仅用于组件,用于监听原生事件,而不是组件内部触发的事件//`vm.$emit`。nativeOn:{click:this.nativeClickHandler},//自定义命令。请注意,您不能在`binding`中为`oldValue`赋值//因为Vue已经自动为您同步了它。directives:[{name:'my-custom-directive',value:'2',expression:'1+1',arg:'foo',modifiers:{bar:true}}],//scopedslots格式is//{name:props=>VNode|Array
}scopedSlots:{default:props=>createElement('span',props.text)},//如果组件是其他组件的子组件,则需要为槽指定一个名称slot:'name-of-slot',//其他特殊的顶级属性key:'myKey',ref:'myRef',//如果你将相同的应用到渲染函数ref名称中的多个元素,//那么`$refs.myRef`将成为一个数组。refInFor:true}vue中render函数的应用:render组成更灵活的组件])你好世界!VirtualDOM结构渲染函数最终生成虚拟DOM。VirtualDom只是一个简单的JS对象,它至少包含三个属性:tag、props和children。VirtualDom格式:{tag:"div",props:{},children:["HelloWorld",{tag:"ul",props:{},children:[{tag:"li",props:{id:1,class:"li-1"},children:["第",1]}]}]}与React中生成虚拟DOM相比,React中的模板渲染定义在render函数中,以下模板:classHelloextendsComponent{render(){returnHelloConardLi
;}}最终会被Babel解析得到一个抽象语法树(AST)然后生成调用createElement的形式,最后生成一个虚拟DOM。下面这种直接调用createElement的形式也可以作为第二种生成模板的方式:}}在Vue中也可以像React一样使用JSX创建模板,需要导入相应的Bable插件(https://github.com/vuejs/jsx):importAnchoredHeadingfrom'./AnchoredHeading.vue'newVue({el:'#demo',render:function(h){return(Helloworld!)}})参考:渲染函数和JSX[React深入】深入剖析虚拟DOM渲染原理及特点