实现将虚拟DOM渲染成DOM结构

200 阅读1分钟

用例数据:

let demoNode = {
    tagName: 'ul',
    props: {'class': 'list'},
    children: [
        {tagName: 'li', children: ['hello']},
        {tagName: 'li', children: ['word']}
    ]
};

定义一个构造函数

/**
 * 
 * @params:
 * tagName(string)(requered)
 * props(object)(optional)
 * children(array)(optional)
 * 
 **/
function Element ({ tagName, props, children }) {
    if (!(this instanceof Element)) {
        return new Element({ tagName, props, children });
    }
    this.tagName = tagName;
    this.props = props || {};
    this.children = children || [];
}

处理数据用例结构

function Init (demoNode) {
    var _elem = new Element(demoNode);
    if (_elem.children) {
        _elem.children.forEach((item, index) => {
            if (item.tagName) {
                _elem.children[index] = new Element(item);
                if (_elem.children[index].children) {
                    Init(_elem.children[index]);
                }
            }
        })
    }
    return _elem;
}

处理后的结构为

elem = Element({
    tagName: 'ul',
    props: {'class': 'list'},
    children: [
        Element({tagName: 'li', children: ['hello']}),
        Element({tagName: 'li', children: ['word']})
    ]
});

渲染函数

Element.prototype.render = function() {
    var el = document.createElement(this.tagName),
        props = this.props,
        propName,
        propValue;
    for (propName in props) {
        propValue = props[propName];
        el.setAttribute(propName, propValue);
    }
    this.children.forEach((child) => {
        var childEl = null;
        if (child instanceof Element) {
            childEl = child.render();
        } else {
            childEl = document.createTextNode(child);
        }
        el.appendChild(childEl);
    })
    return el;
}

测试

const elem = Init(demoNode);
document.querySelector('body').appendChild(elem.render());

最后效果

·hello
·word