深度理解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

 

posted @   Fujijill  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示