DOM操作为什么慢?
答案很简单,因为DOM操作是跨线程的
跨线程操作
- 浏览器分为渲染引擎和JS引擎
- JS引擎不能操作页面,只能操作JS
- 渲染引擎不能操作JS,只能操作页面
而当我们执行document.body.appendChild(div1)时,
这句JS是如何改变页面的?
- 当浏览器发现JS在body里加了一个div1对象
- 浏览器就会通知渲染引擎在页面里也新增一个div元素
- 新增的div元素所有属性都照搬div1对象
如图,就是浏览器操作的这一部分耗费了时间
插入新标签的完整过程
- 在div1放入页面之前
- 对div1的所有操作都只在JS线程里
- 在div1 放入页面之时
- 浏览器会发现JS的意图,并通知渲染线程在页面中渲染div1对应的元素
- 在div1放入页面之后
- 对div1的操作有可能会触发重新渲染,
- div1.id = 'newId'可能会被重新渲染(如果这个Id有CSS的样式)
- div1.title = 'new'(可能会被重新渲染),如:
- 在div后面加了一个伪元素,content的内容就是它属性的title,所以改title就会重新渲染
- 如果对div1连续多次操作,浏览器可能会合并成一次操作
- 这里浏览器发现,你在短时间内对classList进行了两次操作,它就默认把两次合并成了一次,所以不会有动画效果
- 如需出现动画效果,需要加上
test.clientWidth - 示例
属性同步
标准属性
对div1的标准属性的修改,会被浏览器同步到页面中
如id,className,title等
data-*属性
同上
非标准属性
对非标准属性的修改,则只会停留在JS线程中,不会同步到页面里
更改非标准属性示例
执行完代码后,我们自定义的非标准属性x,并没有改变
所以,如果有自定义属性,又想被同步到页面中,应该使用data- 作为前缀
Property与Attribute
- property属性
- JS线程中div1的所有属性,叫做div1的property
- attribute属性
- 渲染引擎中div1对应标签的属性,叫做attribute
区别:
- 大部分时候,同名的property和attribute值相等
- 但如果不是标准属性,那么他俩只会在一开始时相等
- 但注意attribute只支持字符串
- 而property支持字符串,布尔等类型