一.跨线程
浏览器的两个功能模块:渲染引擎,JS引擎,这两个线程各司其职
JS引擎只能操作JS,不能操作页面;渲染引擎只能操作页面,不能操作JS。
那么,当在JS里写 document.body.appendChild(div1)时,JS是怎么把div1放到页面中的?是通过跨线程通信做到的。 浏览器发现JS在body里加了一个div对象,浏览器就通知渲染引擎,往页面的body里也新增一个div元素,他的所有属性照抄div对象。
图示跨线程通信:

在JS中:
-
在div放入页面之前:
let div=document.createElement('div') div.innerText='hi'
创建div,向div插入文本,都属于JS线程内的操作,与DOM无关。
- 在div放入页面之时:
document.body.appendChild(div)
浏览器发现JS要改变页面的内容,就通知渲染引擎在页面中渲染一个div元素。这步是跨线程的。
- 把div放入页面之后:
之后再对div进行的操作都有可能会触发重新渲染。
- 改id可能会重新渲染,如果这个id有颜色之类的样式
div.id='newid' - 甚至改title也有可能会重新渲染


- 如果浏览器发现你连续对div进行了多次操作,浏览器可能会给合并成一次操作,也有可能不会:

因为浏览器发现在短时间内对div的classList进行了两次操作,浏览器就把两次合并成一次渲染了,那怎么不让他合并呢?
可以在JS的两次操作中间加一句
test.clientWidth
获取这个div的客户端宽度,就会出现动画了。获取宽度不会改变其他东西,但是会让浏览器先渲染第一步,先加一个start类,然后再获取宽度,再加end类,这样就不会合并了。
二.属性同步
在JS里改变页面中div元素的innerText,那么页面对应的文本也会修改。是不是在JS里改div的所有属性都会在页面中对应的更改呢?

- 标准属性
对元素的标准属性的修改,会被浏览器同步到渲染页面中。比如 id,className,title等。
- data-*属性
同上,会被同步修改。
- 非标准属性
对非标准属性的修改,如自定义的x属性,只会停留在JS线程内,不会同步到页面里。
如果你有自定义属性,想被同步到页面中,请使用data-作为前缀。
三. Property V.S. Attribute
- property:属性,表示JS线程内div这个对象的所有属性。 id,className,style
- attribute:也是属性,表示渲染引擎内div对应的标签的属性。id,class
如果是同名的标准属性,他们的值会相等。但是如果不是标准属性,可能不会同步更改。