大致流程
var vnode = { tag: 'ul', attrs: { id: 'list' }, children: [{ tag: 'li', attrs: { className: 'item' }, children: ['item 1'] },{ tag: 'li', attrs: { className: 'item' }, children: ['item 2'] }] } function createElement(vnode){ var tag = vnode.tag; var attrs = vnode.attrs || {}; var children = vnode.children || []; if (tag == null) { return null; } // 创建真实的 dom 元素 var elem = document.createElement(tag); // 属性 var attrName; for (attrName in attrs) { if(attrs.hasOwnProperty(attrName)){ elem.setAttribute(attrName, attrs[attrName]); } } // 子元素 children.forEach(function(childVnode){ elem.appendChild(childElem(childVnode)) // 递归 }); // 返回真实的 dom 元素 return elem; }
就是将对象一一转化成dom
上面是patch的第一个参数没有内容的时候,如果有内容就会做对比。
var vnode = { tag: 'ul', attrs: { id: 'list' }, children: [{ tag: 'li', attrs: { className: 'item' }, children: ['item 1'] },{ tag: 'li', attrs: { className: 'item' }, children: ['item 2'] }] } var newVnode = { tag: 'ul', attrs: { id: 'list' }, children: [{ tag: 'li', attrs: { className: 'item' }, children: ['item 1'] },{ tag: 'li', attrs: { className: 'item' }, children: ['item b'] }] } function updateChildren(vnode ,newVnode){ var children = vnode.children || []; var newChildren = newVnode.children || []; children.forEach(function(childrenVnode, index){ var newChildrenVnode = newChildren[index]; if(childrenVnode.tag === newChildrenVnode.tag){ // 深层次对比,递归 updateChildren(childrenVnode, newChildrenVnode); } else { // 替换 replaceNode(childrenVnode, newChildrenVnode); } }); } function replaceNode(vnode, newVnode){ var elem = vnode.elem; // 真实的 dom var newElem = newVnode.elem; // 替换 }
没法知道有多少层,就必须用递归