【字节笔试】给出虚拟dom的数据结构,如何实现简单的虚拟dom,渲染到目标dom树

文章目录

题目描述

给出如下虚拟dom的数据结构,如何实现简单的虚拟dom,渲染到目标dom树

// 样例数据
let demoNode = ({
    
    
    tagName: 'ul',
    props: {
    
    'class': 'list'},
    children: [
        ({
    
    tagName: 'li', children: ['douyin']}),
        ({
    
    tagName: 'li', children: ['toutiao']})
    ]
});

构建一个render函数,将demoNode对象渲染为以下dom

<ul class="list">
    <li>douyin</li>
    <li>toutiao</li>
</ul>

实现

/*
* @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 || [];
}

通过Element我们可以任意地构建虚拟DOM树了。但是有个问题,虚拟的终归是虚拟的,我们得将其呈现到页面中,不然,没卵用。。

怎么呈现呢?

从上面得知,这是一颗树嘛,那我们就通过遍历,逐个节点地创建真实DOM节点:

  1. createElement;
  2. createTextNode;

因为这是一颗树嘛,对于树形结构无外乎两种遍历:

  1. 深度优先遍历(DFS)
    在这里插入图片描述
  2. 广度优先遍历(BFS)在这里插入图片描述
    针对实际情况,我们得采用DFS,为什么呢?
    因为我们得将子节点append到父节点中
    好了,那我们采用DFS,就来实现一个render函数吧,如下:
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(function(child){
    
    
        var childEl = null;
        if(child instanceof Element){
    
    
            childEl = child.render();
        }else{
    
    
            childEl = document.createTextNode(child);
        }
        el.appendChild(childEl);
    });
    return el;
};

此时,我们就可以轻松地将虚拟DOM呈现到指定真实DOM中啦。假设,我们将上诉ul虚拟DOM呈现到页面body中,如下:

var elem = Element({
    
    
    tagName: 'ul',
    props: {
    
    'class': 'list'},
    children: [
        Element({
    
    tagName: 'li', children: ['item1']}),
        Element({
    
    tagName: 'li', children: ['item2']})
    ]
});
document.querySelector('body').appendChild(elem.render());

结果

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_44761091/article/details/123720438