简述DOM跨线程操作

1,531 阅读2分钟

DOM操作为什么慢?
答案很简单,因为DOM操作是跨线程的

跨线程操作

  • 浏览器分为渲染引擎和JS引擎
  • JS引擎不能操作页面,只能操作JS
  • 渲染引擎不能操作JS,只能操作页面

而当我们执行document.body.appendChild(div1)时, 这句JS是如何改变页面的?

  • 当浏览器发现JS在body里加了一个div1对象
  • 浏览器就会通知渲染引擎在页面里也新增一个div元素
  • 新增的div元素所有属性都照搬div1对象

image.png

如图,就是浏览器操作的这一部分耗费了时间

插入新标签的完整过程

  1. 在div1放入页面之前
    • 对div1的所有操作都只在JS线程里
  2. 在div1 放入页面之时
    • 浏览器会发现JS的意图,并通知渲染线程在页面中渲染div1对应的元素
  3. 在div1放入页面之后
  • 对div1的操作有可能会触发重新渲染,
  • div1.id = 'newId'可能会被重新渲染(如果这个Id有CSS的样式)
  • div1.title = 'new'(可能会被重新渲染),如:
    • image.png
    • 在div后面加了一个伪元素,content的内容就是它属性的title,所以改title就会重新渲染
  • 如果对div1连续多次操作,浏览器可能会合并成一次操作
    • image.png
    • 这里浏览器发现,你在短时间内对classList进行了两次操作,它就默认把两次合并成了一次,所以不会有动画效果
    • 如需出现动画效果,需要加上test.clientWidth
    • 示例

属性同步

标准属性

对div1的标准属性的修改,会被浏览器同步到页面中
如id,className,title等

data-*属性

同上

非标准属性

对非标准属性的修改,则只会停留在JS线程中,不会同步到页面里
更改非标准属性示例
执行完代码后,我们自定义的非标准属性x,并没有改变

image.png

所以,如果有自定义属性,又想被同步到页面中,应该使用data- 作为前缀

Property与Attribute

  • property属性
    • JS线程中div1的所有属性,叫做div1的property
  • attribute属性
    • 渲染引擎中div1对应标签的属性,叫做attribute

区别:

  • 大部分时候,同名的property和attribute值相等
  • 但如果不是标准属性,那么他俩只会在一开始时相等
  • 但注意attribute只支持字符串
  • 而property支持字符串,布尔等类型