Vue使用虚拟dom进行渲染视图的方法

  

  

vue版本:v2.5.17-beta。0
  

  

  

vue在数据更新后会自动触发视图的渲染工作,其依赖于数据驱动;在数据驱动的工作下,每一个vue的数据属性都被监听,并且在集触发时,派发事件,通知收集到的依赖,从而触发对应的操作,使工作就是其中的一个依赖,并且被每一个数据属性所收集,因此每一个数据属性改变后,都会触发渲染。

  

  

看一段代码

     //来自mountComponent函数   updateComponent=function () {   vm._update (vm._render(),保湿);   };      新观察家(vm, updateComponent,等待,{   :函数在(){   如果(vm._isMounted) {   callHook (vm, beforeUpdate);   }   }   },真正的/* isRenderWatcher */);      

updateComponent是更新组件的函数,内部调用vm._update,并且传参vm._render ();

  
      <李> vm._render()返回了什么?看源码则得知返回了虚拟dom (VNode)   <李> vm._update函数又做了什么事情?顾名思义,更新传入的vnode李   <李>什么时候触发updateComponent函数?在任何vue的数据属性更改值都会触发   
  

  

阅读_update函数得知,最终调用了vm.__patch__方法,最终找到为createPatchFunction方法的返回值

        var补?createPatchFunction ({nodeOps: nodeOps模块:模块});      Vue.prototype。__patch__=inBrowser & # 63;补丁:无操作;之前      

接下来重点看createPatchFunction的返回函数补丁。

  

如果新的vnode不存在,则注销旧的vnode

        如果(isUndef (vnode)) {   如果(isDef (oldVnode)) {invokeDestroyHook (oldVnode);}   返回   }      

如果旧的vnode不存在,则创建新的vnode

        如果(isUndef (oldVnode)) {//空挂载(可能为组件),创建新的根元素   isInitialPatch=true;   createElm (vnode insertedVnodeQueue);   }      

如果以上不成立,则新的vnode和oldVnode都存在。如果oldVnode不是真实的dom,则为虚拟dom节点,并且新老vnode相似,则进行diff算法

        var isRealElement=isDef (oldVnode.nodeType);   如果(!isRealElement,,sameVnode (oldVnode vnode)) {//修补现有的根节点   patchVnode (oldVnode vnode、insertedVnodeQueue removeOnly);   }      

如果新老vnode不同,则拿到oldVnode的父节点,辅助创建vnode的新节点

        var oldElm=oldVnode.elm;   var parentElm=nodeOps.parentNode (oldElm);//创建新节点   createElm (   vnode。   insertedVnodeQueue,//极其罕见的极端例子:不要插入是否在一个旧的元素//离开过渡。>   如果(oldVnode===vnode) {   返回   }      

如果vnode不是文本节点则有几种情况

        如果(isDef (oldCh),,isDef (ch)) {//如果oldVnode和vnode的孩子都有值(组件层),并且不想等,则执行更新孩子流程   如果(oldCh !==ch) {updateChildren(榆树、oldCh ch、insertedVnodeQueue removeOnly);}   }else if (isDef (ch)) {//如果vnode的孩子有值,如果当前dom有文本则清空,//并将oldVnode的dom作为父节点,创建新vnode的孩子节点   如果(isDef (oldVnode.text)) {nodeOps。setTextContent(榆树,”);}   addVnodes(榆树,null, ch 0 ch.length - 1, insertedVnodeQueue);   }else if (isDef (oldCh)) {//如果oldVnode存在的孩子,但是新的没有,则删除oldVnode的儿童的vnode   removeVnodes (oldCh榆树oldCh 0。长度- 1);   }else if (isDef (oldVnode.text)) {//如果oldVnode有文本信息,则将dom的文本清空   nodeOps。setTextContent(榆树,”);   }      

如果vnode是文本节点,则当新老节点文本不同,将dom的文本更新成新vnode的文本

        else if (oldVnode。文本!==vnode.text) {   nodeOps。setTextContent(榆树,vnode.text);   }      

patchVnode函数处理的情况梳理一下则为:

  
      <李>如果新老vnode相同,不作处理李   <李>如果新vnode是文本节点,并且新老文本不同,将dom更新为vnode的文本李   <李>如果新老vnode都有孩子,表示他们是组件层,则调用updateChildren去做组件层更新   <李>如果新vnode是组件层,oldVnode不是,则将当前dom添加新vnode组件的子元素李   <李>如果oldVnode是组件层,新vnode不是,则操作dom,将oldVnode包含的子元素删除李   <李>如果新vnode是组件层,oldVnode是文本节点,则将dom的文本清空

    Vue使用虚拟dom进行渲染视图的方法