多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
总结:Vue.js通过编译将模版转换成渲染函数(render),执行渲染函数就可以得到一个虚拟节点树(虚拟DOM),虚拟节点树(虚拟DOM)提供虚拟节点vnode和对新旧两个vnode进行比对并根据比对结果进行DOM操作来更新视图,达到减少对DOM的目的,从而减少浏览器的开销,提高渲染速度,改善用户体验。 * patch(container,vnode) :初次渲染的时候,将VDOM渲染成真正的DOM然后插入到容器里面。 * patch(vnode,newVnode):再次渲染的时候,将新的vnode和旧的vnode相对比,然后之间差异应用到所构建的真正的DOM树上。 #### patch(container,vnode) 通过这个函数可以让VNode渲染成真正的DOM,我们通过以下模拟代码,可以了解大致过程: ~~~jsx function createElement(vnode) { var tag = vnode.tag var attrs = vnode.attrs || {} var children = vnode.children || [] if (!tag) { return null } // 创建真实的 DOM 元素 var elem = document.createElement(tag) // 属性 var attrName for (attrName in attrs) { if (attrs.hasOwnProperty(attrName)) { // 给 elem 添加属性 elem.setAttribute(attrName, attrs[attrName]) } } // 子元素 children.forEach(function (childVnode) { // 给 elem 添加子元素,如果还有子节点,则递归的生成子节点。 elem.appendChild(createElement(childVnode)) // 递归 }) // 返回真实的 DOM 元素 return elem } ~~~ #### patch(vnode,newVnode) 这里我们只考虑vnode与newVnode如何对比的情况: ~~~php function updateChildren(vnode, newVnode) { var children = vnode.children || [] var newChildren = newVnode.children || [] // 遍历现有的children children.forEach(function (childVnode, index) { var newChildVnode = newChildren[index] // 两者tag一样 if (childVnode.tag === newChildVnode.tag) { // 深层次对比,递归 updateChildren(childVnode, newChildVnode) } else { // 两者tag不一样 replaceNode(childVnode, newChildVnode) } } )} ~~~ > diff程可以概括为: oldCh和newCh各有两个头尾的变量StartIdx和EndIdx,它们的2个变量相互⽐较,⼀共有4种 ⽐较⽅式。 如果4种⽐较都没匹配,如果设置了key,就会⽤key进⾏⽐较,在⽐较的过程中,变量会往中间靠, ⼀旦StartIdx>EndIdx表明oldCh和newCh⾄少有⼀个已经遍历完了,就会结束⽐较。 这四种⽐较⽅式就是⾸、尾、 旧尾新头、旧头新尾.