一个能代表DOM树的对象,通常含有标签名、标签上的属性、事件监听和子元素们,以及其他的属性
const vNode ={ type:'div', props:{ class:'className', on:{ click:() => {} } }, children:[ {type:'span',props:{},children:[]}, {type:'span',props:{},children:[]} ] }
Vue(只能通过render函数里得到createElement,经过createElement函数编译之后生成虚拟DOM的对象结构) createElement( 'div', { class:'className', on:{ click:() => {} } }, [ createElement('span',{},'span1=>text'), createElement('span',{},'span2=>text2') ] ) 但是在vue一般写成(Vue Template)
虚拟DOM可以将多次操作合并为一次操作,比如你添加1000个节点,却是一个接着一个操作的(不是优化DOM操作,只是减少DOM操作的次数) 虚拟DOM借助DOM diff可以把多余的操作省掉,比如你添加1000个节点,其实只有10个是新增加的(减少DOM操作的范围)
虚拟DOM(实际就是一个对象来表示节点元素)不仅可以变成DOM,还可以变成小程序、ios应用、安卓应用,因为虚拟DOM本质只是一个JS对象(Object表示节点元素)
需要用额外的创建函数来创建虚拟DOM对象,如vue中使用 createElement,但可以通过vue-loader来简化写法
严重依赖打包工具,因为vue-loader是打包工具里面内置的,添加额外的构建过程
是虚拟DOM的对比算法,就是一个函数,我们称之为patch
Tree diff 将新旧两棵树逐层对比,找出那些节点需要更新 如果节点是组件就看Component diff 如果节点是标签就看Element diff
如果节点是组件,就先看组件类型 类型不同直接删除(删除旧的) 类型相同只更新属性 然后深入组件做Tree diff(递归)
如果节点是原生标签,则看标签名 标签名不同直接替换,相同则只更新属性 然后进入标签后代做Tree diff(递归)
当生成虚拟DOM的时候,会重新排列节点顺序,新旧虚拟DOM会根据key进行对比,当删除一个树的左孩子的时候右孩子自动变成左孩子,如果没有key,diff算法新旧DOM对比就会拿之前 的左孩子和新的虚拟DOM的右孩子进行对比,看看发生什么变法,在进行相应的变化,但是你加上key之后,diff算法就会直接删除新的虚拟DOM的右孩子,只进行一步操作。