写一个自己的虚拟DOM(二)

作者: 蚊子爸爸 | 来源:发表于2017-12-02 20:53 被阅读46次

    将虚拟DOM转变成为真实的DOM

    现在我们有了一个纯粹的JS对象来代表一个DOM树,下一步要做的是按照这个虚拟DOM来创造一个真的DOM。在此之前需要先做一些约定:

    1. 以美元符号$开头的变量代表真实DOM。
    2. 变量node代表虚拟DOM。
    3. 只能有一个根节点。

    好,我现在要写一个按照虚拟DOM来创造真实DOM的函数,名为createElement(...),这个函数接收一个虚拟DOM作为参数,返回一个真实DOM。为了简便起见,暂时先不考虑props属性和children属性,这些东西以后再完善。

    function createElement(node){
        if(typeof node ==='string'){
            return document.createTextNode(node);
        }
        const $el = document.createElement(node.type);
        node.children.map(createElement).forEach($el.appendChild.bind($el));
        return $el;
    }
    

    这个createElement方法是不是看起来有点复杂,这是因为里面加了一些奇技淫巧,事实上如果你自己用本方法,可以写出来虽然冗长但是通俗易懂的实现,我写成这样是为了排版好看。说白了,这个createElement方法只是一个递归调用,使用了document对象的createElement方法和createTextNode方法以及DOM对象的appendChild方法,只有这三个方法而已。
    如果你对上面这段代码很困惑,那么没关系,请跳过,这篇文章主要介绍的是思路,而不是具体实现。
    好了,现在我可以根据一个虚拟DOM来生成一个真实的DOM了,来看看我现在的代码:

    /** @jsx h */
    
    function h(type, props, ...children) {
      return { type, props, children };
    }
    
    function createElement(node){
        if(typeof node ==='string'){
            return document.createTextNode(node);
        }
        const $el = document.createElement(node.type);
        node.children.map(createElement).forEach($el.appendChild.bind($el));
        return $el;
    }
    
    const a = (
      <ul class="list">
        <li>item 1</li>
        <li>item 2</li>
      </ul>
    );
    
    
    const DOM = createElement(a);
    const root = document.getElementById("root");
    root.appendChild(DOM)
    

    我的JSFiddle代码

    现在这个代码可以顺利地将虚拟DOM产生为一个真实DOM并且显示在页面上了。

    image.png

    下一部分会写虚拟DOM的diff算法。其实就是如何比对两个虚拟DOM,找出不同,并且在真实DOM上做出反应。

    相关文章

      网友评论

      • 阡陌夕殇:好期待下面的文章,求快更:joy:
        蚊子爸爸:@阡陌夕殇 今天正在写diff算法,可是写来写去觉得无论如何也难表达的非常清楚,现在还在构思

      本文标题:写一个自己的虚拟DOM(二)

      本文链接:https://www.haomeiwen.com/subject/rawnbxtx.html