虚拟 dom 原理是啥?手写一个简单的虚拟 dom 实现?

发布于 2023-09-14 13:57:37 字数 2657 浏览 40 评论 0

vdom 概念

用 JS 模拟 DOM 结构。DOM 变化的对比,放在 JS 层来做。提升重绘性能。

比如有 abc 三个 dom, 如果我们要删除 b dom, 以前浏览器的做法是 全部删除 abc dom , 然后 在添加 b dom 。这样做的成本会非常高。

用 JS 模拟 dom

例如下面的一个 dom 结构:

<ul>
    <li class="item">item1</li>
    <li class="item">item2</li>
</ul>

这样的 dom 结构,可以模拟为下面的 JS :

let dom = {
    tag: 'ul',
    attrs: {
        id: 'list'
    },
    children: [
        {
            tag: 'li',
            attrs: {className: 'item'},
            children: ['item1']
        },
        {
            tag: 'li',
            attrs: {className: 'item'},
            children: ['item2']
        }
    ]
}

浏览器操作 dom 是花销非常大的。执行 JS 花销要小非常多,所以这就是为什么虚拟 dom 出现的一个根本原因。

jquery 实现 virtual-dom

一个需求场景

1、数据生成表格。 2、随便修改一个信息,表格也会跟着修改。

<body>
<div></div>
<br>
<button>change</button>
<script>
    let data = [
        {
            name: 'yanle',
            age: '20',
            address: '重庆'
        },
        {
            name: 'yanle2',
            age: '25',
            address: '成都'
        },
        {
            name: 'yanle3',
            age: '27',
            address: '深圳'
        }
    ];

    // 渲染函数
    function render(data) {
        let $container = document.getElementById('container');
        $container.innerHTML = '';

        let $table = document.createElement('table');
        $table.setAttribute('border', true);
        $table.insertAdjacentHTML('beforeEnd', `<tr>
                                    <td>name</td>
                                    <td>age</td>
                                    <td>address</td>
                                    </tr>`);

        data.forEach(function (item) {
            $table.insertAdjacentHTML('beforeEnd',
                `<tr>
                    <td>${item.name}</td>
                    <td>${item.age}</td>
                    <td>${item.address}</td>
                </tr>`
            )
        });

        $container.appendChild($table);
    }

    // 修改信息
    let button = document.getElementById('btn-change');
    button.addEventListener('click', function () {
        data[1].name = '徐老毕';
        data[1].age = 30;
        data[1].address  = '深圳';
        render(data);
    });
    render(data);
</script>
</body>

实际上上面的这段代码也是不符合预期的,因为每次使用 render 方法,都会全部渲染整个 table, 但是并未没有只渲染我们想要的第二行。

遇到的问题

DOM 操作是非常 昂贵 的, JS 运行效率高。虚拟 dom 的核心就是 diff 算法,对比出不同的 dom 数据,定点渲染不同的数据。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

自由如风

暂无简介

文章
评论
25 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文