React 编译渲染原理实现 发表于 2017-05-12 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091class React { constructor() { }; static createElement(type, options, ...arg) { options = options || {}; // arg 储存的是剩下的参数集合,没有的话就是空数组 let obj = {type, key: null, ref: null, props: {}}; ['key', 'ref'].forEach(item => { if (item in options) { obj[item] = options[item]; delete options[item] } }); obj.props = {...options}; let len = arg.length; switch (len) { case 0: // 没有子节点,没有children break; case 1: // 只有一个子节点,children 不是一个数组 obj.props.children = arg[0]; break; default: // 多个子节点 obj.props.children = JSON.parse(JSON.stringify(arg)) } return obj }}class ReactDOM { static handChild(children, newEle) { if (typeof children === 'object') { // children 是一个虚拟dom ReactDOM.render(children, newEle) } else { // children 是一个字符串 newEle.appendChild(document.createTextNode(children)) } } static render(objJSX, container, cb) { let {type, props} = objJSX, newEle = document.createElement(type); for (let key in props) { if (!props.hasOwnProperty(key)) continue; if (key === 'children') { let children = props['children']; if (children instanceof Array) { // children 是数组 children.forEach(itemChild => { ReactDOM.handChild(itemChild, newEle) }); continue } // 只有一个子节点 ReactDOM.handChild(); continue; } // class if (key === 'className') { newEle.setAttribute('class', props['className']); continue; } // style 把props中的style的值依次遍历,并设置给元素 if (key === 'style') { for (let key in props['style']) { if (!props['style'].hasOwnProperty(key)) continue; newEle.style[key] = props['style'][key] } } newEle.setAttribute(key, props[key]) } container.appendChild(newEle); cb && cb() }}React.createElement('div', undefined);styleObj = {color: 'red'};