深度理解Virtual Dom
本质:维护状态更新视图
Virtual DOM 算法
DOM 树上的结构、属性信息我们都可以很容易地用 JavaScript 对象表示出来。
1 2 3 4 5 6 7 8 9 10 11 | var olE = { tagName: 'ol' , // 标签名 props: { // 属性用对象存储键值对 id: 'ol-list' }, children: [ // 子节点 {tagName: 'li' , props: { class : 'item' }, children: [ "Item 1" ]}, {tagName: 'li' , props: { class : 'item' }, children: [ "Item 2" ]}, {tagName: 'li' , props: { class : 'item' }, children: [ "Item 3" ]}, ] } |
对应 HTML 写法是:
<ol id='ol-list'> <li class='item'>Item 1</li> <li class='item'>Item 2</li> <li class='item'>Item 3</li> </ol>
用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文
档当中当状态变更时,重新构造一棵新的对象树。然后用新的树和旧的树进行比较两个数的差异。
然后把差异更新到久的树上,整个视图就更新了。Virtual DOM 本质就是在 JS 和 DOM 之间做
了一个缓存。既然已经知道 DOM 慢,就在 JS 和 DOM 之间加个缓存。JS 先操作 Virtual DOM
对比排序/变更,最后再把整个变更写入真实 DOM。
Virtual DOM实现
1 2 3 4 5 6 | import * as el from 'Ele' ; var ol = el( 'ol' , {id: 'ol-list' }, [ el( 'li' , { class : 'item' }, [ 'Item 1' ]), el( 'li' , { class : 'item' }, [ 'Item 2' ]), el( 'li' , { class : 'item' }, [ 'Item 3' ]) ]); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | Ele.prototype.render = function () { var e = document.createElement( this .tagName); // 创建元素 var props = this .props; for ( var propName in props) { // 设置 DOM 属性 var propValue = props[propName]; e.setAttribute(propName, propValue); } var children = this .children || []; children.forEach( function (child) { var childE = (child instanceof Element) ? child.render() // 子节点也是虚拟 DOM,递归构建 : document.createTextNode(child); // 字符串,构建文本节点 e.appendChild(childE); }); return e; } |
最后只需要 render。
var olE = Ele.render() document.body.appendChild(olE);
上面的 olE 是真正的 DOM 节点,把它 append 到 body 中,这样就有了真正的 ol DOM 元素。
Virtual DOM 树的差异介绍(Diff算法)
比较两个 DOM 树的差异是 Virtual DOM 算法最核心的部分,这也是所谓的 Virtual DOM 的
diff 算法。在前端当中,很少会跨越层级地移动 DOM 元素。所以 Virtual DOM 只会对同一个
层级的元素进行对比,下面的 div 只会和同一层级的 div 对比,第二层级的只会跟第二层级对
比。采用的是深度优先遍历,来记录差异,这样每个节点都会有一个唯一的标记。
差异是指的是什么呢?DOM 替换掉原来的节点,如把上面的 div 换成了 section 进行移动、删
除、新增子节点,例如上面 div 的子节点,把 p 和 span 顺序互换修改了节点的属性。对于文本
节点,文本内容可能会改变。
如果我把左侧的 p、span、div 反过来变成 div、p、span 怎么办?按照差异正常会被替换掉,
但这样 DOM开销就会异常的大了。而 React 帮我们做到不需要替换节点,而只需要经过节点移
动就可以达到。
参考链接 ,转载自:https://www.cnblogs.com/wubaiqing/p/6726429.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?