【JS提升】浅谈从DOM操作到虚拟DOM

一、虚拟DOM

(1)概念

虚拟DOM(Virtual DOM)-> Vue React核心

通过JS去模拟DOM结构

比如把表单里的abc改成dbc,用JQuery的话就会先去除abc,再改成dbc,这样就比较消耗性能

如果用虚拟DOM的话,就只需要修改更改的内容就可以了,这样性能相对的提升了

(2)snabbdom

snabbdom是一个虚拟DOM库

h函数: 帮助生成一个虚拟的dom节点

// 第一个参数是类名、第二个参数是属性,第三个参数是子节点
var vnode = h("ul#list", {}, [
    h("li.list-item", {}, "first item"),
    h("li.list-item", {}, "second item")
])

对应的虚拟dom结构:

{
    tag: 'ul',
    attrs: {
        id: 'list'
    },
    children: [
        {
            tag:'li',
            attrs: { className: 'list-item' },
            children: ['first item']
        },
        {
            tag: 'li',
            attrs: { className: 'list-item' },
            children: ['second item']
        }
    ]
}

patch函数:

如果第一个参数是node,就会被第二个参数的vnode替换

如果两个都是vnode会进行对比,更新或增加相对应的vnode

patch(container, vnode);
patch(vnode, newVnode);

(3)diff算法

比较两个文件之间的不同

snabbdom就是利用diff算法找出dom里面需要更新的节点有哪些

示例1

用JQuery做点击改变按钮修改container里面的内容

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <div id="container"></div>

    <button id="changeBtn">改变</button>

    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <script>
        var data = [
            {
                name: "张三",
                age: 20,
                job: "司机"
            },
            {
                name: "李四",
                age: 30,
                job: "银行职员"
            },
            {
                name: "王五",
                age: 40,
                job: "公司经理"
            }
        ]

        // 渲染函数
        function render(data) {
            var $container = $('#container');

            //  清空
            $container.html('');

            // 拼接table
            var $table = $("<table>");
            $table.append($("<tr><td>姓名</td><td>年龄</td><td>职位</td><tr>"));
            data.forEach(function (item) {
                $table.append($("<tr><td>" + item.name + "</td><td>" + item.age + "</td><td>" + item.job + "</td><tr>"));
            });

            // 渲染到页面
            $container.append($table);
        }

        $('#changeBtn').click(function () {
            data[0].name = "赵六";
            data[1].job = "飞行员";

            // 重新渲染
            render(data);
        });

        // 初次渲染
        render(data);
    </script>
</body>

</html>

点击发现整个container,及table都在闪烁,说明对他们都进行了修改

示例2

用虚拟dom来做点击改变修改container里面的内容

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <div id="container">
    </div>

    <button id="changeBtn">改变</button>

    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/snabbdom/0.7.4/snabbdom.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/snabbdom/0.7.4/snabbdom-class.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/snabbdom/0.7.4/snabbdom-props.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/snabbdom/0.7.4/snabbdom-style.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/snabbdom/0.7.4/snabbdom-eventlisteners.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/snabbdom/0.7.4/h.min.js"></script>
    <script>
        var container = document.getElementById('container'),
            changeBtn = document.getElementById('changeBtn');
        var snabbdom = window.snabbdom;

        // 定义patch函数
        var patch = snabbdom.init([
            snabbdom_class,
            snabbdom_props,
            snabbdom_style,
            snabbdom_eventlisteners
        ]);

        // 定义h函数
        var h = snabbdom.h;

        // 生成vnode
        var vnode = h("ul#list", {}, [
            h("li.list-item", {}, "first item"),
            h("li.list-item", {}, "second item")
        ]);
        patch(container, vnode);

        changeBtn.addEventListener("click", function () {
            // 生成新的vnode
            var newVnode = h("ul#list", {}, [
                h("li.list-item", {}, "第一个item"),
                h("li.list-item", {}, "second item"),
                h("li.list-item", {}, "third item")
            ]);
            patch(vnode, newVnode);
            // 已经存在就不会替换,只会替换没有的或有变化的
        });
    </script>
</body>

</html>

发现只有修改的内容在闪烁,也就是只修改了更改过的内容

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值