Skip to content

Vue2的虚拟DOM -- 源码剖析 ​

  1. Vue的核心流程
    • 将数据先处理成响应式,initState,(针对对象来说主要是增加defineProperty,针对数组就是重写方法)
    • 模板编译,将模板先转换成了ast语法树(使用正则,效率不高)
    • 再将ast语法树生成了render函数
    • 调用render函数,会进行取值操作,产生对应的虚拟DOM,触发get方法 render(){_c('div',null,_v(name))}
    • 将虚拟DOM渲染成真实DOM _update
    • 后续每次数据更新可以只执行render函数(无需再次执行ast转化的过程)
      js
        export function initLifecycle(Vue){
          Vue.prototype._update = function(vnode){//将vnode转化成真实dom
              const vm = this;
              const el = vm.$el;
            // patch既有初始化的功能又有更新
            vm.$el = patch(el, vnode);
          }
        }
        function patch(oldVNode , vnode){
          //写的是初渲染流程
          const isRealElement = oldvNode.nodeType;
          if(isRealElement){//首次创建
            const elm = oldvNode;  //获取真实元素
            const parentElm = elm.parentNode;//拿到父元素
            let newEln = createElm(vnode);
            parentElm.insertBefore(newElm,elm.nextSibling); //在老节点的下一个兄弟节点处插入
            parentElm.removeChild(elm);//删除老节点          
            return newElm
          }else{
              // diff算法
          }
        }
        function createElm(vnode){
          let {tag,data,children,text} = vnode;
          if(typeof tag --- "string "){ //标签
            vnode.el = document.createElemen(tag);//这里将真实节点和虚拟节点对应起来,后续如果修改属性了,可以通过这个找到
            patchProps(vnode.el,data);//创建属性
            children.forEach(child =>{
              vnode.el.appendchild(createElm(child)) //添加节点
            });
          }else{
            vnode.el = docunent.createTextNode(text)  //创建文本节点
          }
          return vnode.el
        }   
      
        function patchProps(el,props){
          for(let key in props){
            if(key === "style"){ // style{color : "red"}
                for(let styleName in props.style){
                  el.style[styleNane] = props.style[styleName]; //style属性赋值
                }
              }else{
                el.setAttribute(key,props[key]);//生成属性
            }
          }
        }
  2. ast和vDom不一样
    • ast做的是语法层面的转化,他描述的是语法本身(可以是html css js)
    • 虚拟Dom描述的是dom元素,可以增加一些自定义属性