Vue2的虚拟DOM -- 源码剖析
- 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]);//生成属性 } } }
- ast和vDom不一样
- ast做的是语法层面的转化,他描述的是语法本身(可以是html css js)
- 虚拟Dom描述的是dom元素,可以增加一些自定义属性