什么是回流与重绘?
当render tree中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建。这就称为回流(reflow)。每个页面至少需要一次回流,就是在页面第一次加载的时候。在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程成为重绘。
当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。则就叫称为重绘。
注意:回流必将引起重绘,而重绘不一定会引起回流。
JS文档碎片
将需要添加到dom中的内容一次性添加到文档碎片中,然后将文档碎片添加到dom树,这样就可以有效的减少操作dom的次数以达到减少回流和重绘的目的来提高性能。
nodeFragment(el){
const f = document.createDocumentFragment()
f.appendChild(el.firstChild)
}
compile
具有解析v-指令编译模板、追加文档碎片、更新视图的功能,用到的原理主要就是操作原生js的node及运用其属性nodetype(判断节点)和attributes(拿到并解析v-split(-)指令和{{ }}【用正则表达式】以及事件(node.addEventListener()))然后通过构建updater进行数据的识别(split(.)进行分割指令然后使用reduce进行分层识别(person.name))和更新(node.innerHTML/node.value/node.textContent)当实现双向绑定(即由视图改数据之前是数据改视图),就需要在compile中用node.addEventListener()绑定原生事件并用回调函数进行setValue()[附带解析指令的自构函数]
class Compile{
constructor(el,vm){
this.el = this.isElementNode(el) ? el : document.querySelector(el)
this.vm = vm
//获取文档碎片对象放入内存减少页面回流和重绘
const fragment = this.nodeFragment(this.el)
//编译模板
this.compile(fragment)
//追加子元素到根元素
this.el.appendChild(fragment)
}
compile(fragment){
//1.获取子节点
const childNodes = fragment.childNodes;
[...childNodes].forEach(child => {
if(this.isElementNode(child)){
//编译元素节点
this.compileElement(child)
}else{
//编译文本节点
this.compileText(child)
}
})
}
}