React源码实现

248 阅读1分钟

createElement


render


/**
 * 
 * @param {*} vdom 虚拟 DOM React元素
 * @param {*} container 真实的 DOM 容器
 */
function render(vdom, container) {
    mount(vdom, container)
}

function mount(vdom, parentDOM) {
    const newDOM = createDom(vdom); // 把虚拟 DOM 变成 真实 DOM
    parentDOM.appendChild(newDom); // 把真实 DOM 添加到容器上
}

function createDom(vdom) {
    let { type, props } = vdom;
    let dom;
    if(type === REACT_TEXT) { // 创建文本节点
        dom = document.createTextNode(props.content)
    }else { // 创建DOM节点
        dom = document.createElement(type)
    }

    if(props) { // 处理属性
        updateProps(dom, {}, props);
        let children = props.children;
        if(typeof children === 'object' && children.type) { // 是个元素
            render(children.dom) // render叫mount合适
        }else if(Array.isArray(children)) {
            reconcileChidlren(children, dom)
        }
    }
    vdom.dom = dom; // 放置一个 DOM 只想此虚拟 DOM 对应的真实DOM
    return vdom;
}

function reconcileChidlren(children, parentDom) {
    children.forEach(childVdom => render(childVdom, parentDom));
}

function updateProps(dom, oldProps, newProps) {
    for (let key in newProps) {
        if (key === 'children') {
            continue;
        } else if (key === 'style') {
            let styleObj = newProps[key];
            for (let attr in styleObj) {
                dom.style[attr] = styleObj[attr];
            }
        } else {
            dom[key] = newProps[key]
        }
    }
}