从头实现一个简易版的React虚拟dom和diff算法

168 阅读1分钟

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8" />
    <title>从头实现一个简易版的React虚拟dom和diff算法</title>
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
</head>

<body>
    <div id="root"></div>
    <script>
    //虚拟dom
    function Element(tagName, props, children) {
        this.tagName = tagName
        this.props = props || {};
        this.children = children;
    }

    Element.prototype.render = function() {
        var el = document.createElement(this.tagName)
        var props = this.props

        for (var propName in props) {
            var propValue = props[propName]
            el.setAttribute(propName, propValue)
        }

        var childEl = document.createTextNode(this.children);
        el.appendChild(childEl)

        return el
    }

    //diff算法
    function diff(oldTree, newTree) {
        var patches = {}
        var propsPatches = {}
        var oldProps = oldTree.props
        var newProps = newTree.props
        for (key in oldProps) {
            value = oldProps[key]
            if (newProps[key] !== value) {
                propsPatches[key] = newProps[key]
            }
        }
        patches.props = propsPatches;
        return patches
    }

    //更新到页面上
    function patch(node, patches) {
        for (let prop in patches.props) {
            node.setAttribute(prop, patches.props[prop]);
        }
    }

    let tree = new Element('div', { 'data-msg': 'xu' }, 'xu');
    let html = tree.render();
    $('#root').html(html);

    let index = 0;
    setInterval(function() {
        index = index + 1;
        var newTree = new Element('div', { 'data-msg': 'xu' + index }, 'xu');
        var patches = diff(tree, newTree)
        console.log(patches)
        patch(html, patches)
        tree = newTree
    }, 1000)
    </script>
</body>

</html>