function createElement(type, config, children) { // 1. 创建一个对象 // 2.根据参数config修改这个对象 // 3.把children参数作为对象中props中的一个属性 let virtureDOM = {}; virtureDOM.type = type; virtureDOM.ref = config.ref || null; virtureDOM.key = config.key || null; let props = {}; // 虚拟dom的props for (const attr in config) { // 遍历config 把除去ref和key的属性值复制到props中 if (attr === 'key' || attr === 'ref') continue; else props[attr] = config[attr]; } const childrenLength = arguments.length - 2;// create可以传多个参数 第三个开始被认为是children if (childrenLength === 1) { props.children = children; // 如果只有一个 那么children就是第三个参数 } else if (childrenLength > 1) { let childArray = Array(childrenLength); // 如果不止一个,就存入childArray数组中 for (let i = 0; i < childrenLength; i++) { childArray[i] = arguments[i + 2]; } props.children = childArray; } virtureDOM.props = props; return virtureDOM; } // 把创建的对象转为真实DOM元素最后插入到页面中 function render(virtureDOM, container, callback) { let { type, props } = virtureDOM || {}; let realDom = document.createElement(type); for (let attr in props) { if (!props.hasOwnProperty(attr)) break; // 如果不是私有属性 直接跳出 说明已经遍历到原型上了 if (!props[attr]) continue; // 如果这个attr没有有效值,那么继续找下一个 const val = props[attr]; // 处理classname变成class if (attr === 'className') realDom.setAttribute('class', val); else if (attr === 'children') { // 处理children if (typeof val === 'string') { // 如果只有一个字符串children 那么直接渲染text出来 let text = document.createTextNode(val); realDom.appendChild(text); } else if (val instanceof Array) { // 如果children是数组, 那么就得遍历这个数组分情况再渲染 for (let i = 0; i < val.length; i++) { if (typeof val[i] === 'string') { let text = document.createTextNode(val[i]); realDom.appendChild(text); } else { render(val[i], realDom); } } } else { // 如果children只有一个且不是数组也不是字符串 那么应该是createElement出来的虚拟dom。递归 render(val, realDom); } } else if (attr === 'style') { // 处理style属性 if (val === '') continue; // style 有可能值为空字符串 for (let sty in val) { if (val.hasOwnProperty(sty)) realDom['style'][sty] = val[sty]; } } else realDom.setAttribute(attr, val); // 基于setAttribute可以让设置的属性表现在html的结构上 } container.appendChild(realDom); callback && callback(); } const virtureDom2 = createElement('span', {}, 'age is 18!'); const virtureDom = createElement('div', { id: 'box', className: 'lp', style: { color: 'red' }, key: 12, ref: 'refs' }, 'my name is LanPang ', virtureDom2); render(virtureDom, document.getElementById('root'), () => console.log('finish'));