1. Patch 是什么
举个例子,桌面上依此摆放着🍎🍐🍑🥝,需要经过某些步骤,将桌面上的水果调整为🍑🍐🥝🍉。
- 方法一:学习我们非凡桌面清理大师。
1.清空桌面
2.依次摆放好🍑🍐🥝🍉
- 方法二:基于前后差异调整,这就是 Patch 了。
1.🍎去掉
2.🍑移动到🍐的前面
3.在末尾加入🍉
Patch,[pætʃ],补丁的意思,寻找前后两版的差异进行逐个调整的过程。实际的场景中,一组 DOM 的结构可能比例子中的列表复杂的多,因此需要一种描述蓝本的结构。一个 JS 对象表示一个元素怎么样,这就是VirtualDOM,后面简称 vnode。
如很多文章提到的一样, Patch 算法减少了 DOM 操作,避免了不必要的开销,提升性能。
真的是这样吗?
2. Patch 有用吗
回顾开头例子的两种方法,方法一的 DOM 操作步骤较少,实际的操作过程可能是这样:
wrap.innerHTML = '';
wrap.innerHTML = '<div>...</div>';
而方法二可以复用一部分 DOM ,但步骤可能根据数据状况变多,实际的操作过程可能是这样:
wrap.insertBefore
wrap.removeChild
wrap.setAttribute
wrap.removeAttribute
...
因此,关键是探究 DOM 复用和 DOM 操作次数哪个对性能的影响更大?
设计实验
初始有较多(10000+)的 li 标签,通过通过三种方式完成 DOM 更新,比较更新时长。
<ul class="wrap"><li></li><li></li><li></li>...
</ul>
- 方法一 (全量替换, DOM 操作次数多)
wrap.innerHTML = '';
for(let i = 0; i < 10000; i++) {const el = document.createElement('li');el.className = 'item1';wrap.appendChild(el);
}
- 方法二 (全量替换, DOM 操作次数少)
wrap.innerHTML = '';
let str = ''
for(let i = 0; i < 10000; i++) {str += '<li class="item2"></li>';
}
wrap.innerHTML = str;
- 方法三 ( DOM 复用, DOM 操作次数多)
const children= [...wrap.childNodes];
const length = children.length;
for(let i = 0; i < length; i++) {if (!(i % 3)) {const el