随笔 - 148  文章 - 0  评论 - 13  阅读 - 21万

虚拟dom详解

什么是vdom

顾名思义虚拟dom并非真实的dom,而是由按照一定的规则构成的可对真实dom进行描述的 JS对象。
结构如下

//虚拟dom
{
      tag:'ul',
      attrs :{id:'list'},
      children:[{tag:'li',attrs:{className:'li'},children:['item1']},{tag:'li',attrs:{className:'li'},children:['item2']},{tag:'li',attrs:{className:'li'},children:['item3']}]
}
//真实dom
<ul id="list">
     <li class="li">item1</li>
     <li class="li">item1</li>
     <li class="li">item1</li>
</ul>

为什么要使用虚拟dom

1.dom操作是昂贵的,并且会引发浏览器的回流和重绘耗费性能
2.将 DOM 对比操作放在 JS层,提高效率
3.浏览器只渲染相应的需要改变的dom,减小回流,重绘成本

如何使用虚拟dom

使用:可用 snabbdom 的用法来举例
h函数 - 用于生成虚拟dom
patch函数
patch('container',vdom) 将虚拟dom渲染到 界面上 (createElement)
patch (vdom,newVdom) 对比新旧虚拟dom,找出差异,并将差异部分在界面上进行改变 ( updateChildren)

如何理解diff算法

1 是 linux 的基础命令
2 vdom 中应用 diff 算法是为了找出需要更新的节点
3 实现,patch(container, vnode) 和 patch(vnode, newVnode)
4 核心逻辑,createElement 和 updateChildren

createElement.js

function createElement(vnode) {
    var tag = vnode.tag  // 'ul'
    var attrs = vnode.attrs || {}
    var children = vnode.children || []
    if (!tag) {
        return null
    }

    // 创建真实的 DOM 元素
    var elem = document.createElement(tag)
    // 属性
    var attrName
    for (attrName in attrs) {
        if (attrs.hasOwnProperty(attrName)) {
            // 给 elem 添加属性
            elem.setAttribute(attrName, attrs[attrName])
        }
    }
    // 子元素
    children.forEach(function (childVnode) {
        // 给 elem 添加子元素
        elem.appendChild(createElement(childVnode))  // 递归
    })

    // 返回真实的 DOM 元素
    return elem
}

updateChildren.js

function updateChildren(vnode, newVnode) {
    var children = vnode.children || []
    var newChildren = newVnode.children || []

    children.forEach(function (childVnode, index) {
        var newChildVnode = newChildren[index]
        if (childVnode.tag === newChildVnode.tag) {
            // 深层次对比,递归
            updateChildren(childVnode, newChildVnode)
        } else {
            // 替换
            replaceNode(childVnode, newChildVnode)
        }
    })
}

function replaceNode(vnode, newVnode) {
    var elem = vnode.elem  // 真实的 DOM 节点
    var newElem = createElement(newVnode)

    // 替换
}
posted on   长安城下翩翩少年  阅读(350)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示