浏览器

86 阅读3分钟

内核

内核就是负责 浏览器 核心部分的代码: 负责解析 js, css, html 和网络交互, 事件响应等功能

浏览器重绘重排

回流/重拍 重绘 在Render tree中, 如果因为元素的尺寸, 布局, 隐藏等改变,需要重新构建, 这就是成为回流(reflow). 每一个页面至少需要一次回流, 就是在页面第一次加载的时候. 在回流的时候, 浏览器会让渲染树中的收到影响的部分失效, 并重新构造这部分渲染树, 完成回流之后, 浏览器会重新绘制收到影响的部分, 分到屏幕中,该过程为重绘

回流/重排 毕竟引起重绘, 而重回不一定会引起回流. 回流会导致渲染树重新计算, 开销比重绘大,所以我们要尽量避免回流的产生

  • 重排/回流的产生:
    1. 页面初次渲染的时候, 所有组建都要首次布局, 这是开销最大的一次 重排/回流;

    2. 浏览器尺寸改变

    3. 位置信息和尺寸发生改变

    4. 新增和删除可见元素

    5. 元素字体大小变化

    6. 激活css伪类 (:hover);

    7. 内容发生变化(文字数量和图片大小)

    8. 设置style属性

    9. 查询或者调用某写方法: offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight

    10. getComputeStyle

这些都会触发重排, 因为原理都是一样,都是为一个即时性和准确性

  • 重绘的产生:

    1. 当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如 : visibility、outline、背景色等属性的改变
  • 常见的额避免方法:

    1. 尽量通过 class 和 cssText 进行集中改变样式
    // bad
    var left =10;
    var top =10;
    element.style.left = left+'px';
    element.style.top = top+'px;
    // good
    el.className += ' className';
    // or
    el.style.cssText += "; left: " + left + "px; top: " + top + "px;";
    
    1. 我们只需要使用一个局部变量缓存这些需要查询的值,高密度执行的操作中(拖拽等操作)这些值暂时会使用这个缓存的值而不是每次使用上述的那些信息时都要触发reflow和repaint操作
    	// bad 强制刷新 触发两次回流
    	div.style.left = div.offsetLeft + 1 + 'px';
    	div.style.top = div.offsetTop + 1 + 'px';
    	// good 缓存布局信息 相当于读写分离
        // 把 curLeft 值临时给存起来
        // 把 curRight 值临时给存起来
    	var curLeft = div.offsetLeft;
    	var curTop = div.offsetTop;
    	div.style.left = curLeft + 1 + 'px';
    	div.style.top = curTop + 1 + 'px';   
    	div1.style.left = curLeft +2+'px';
    	div1.style.left = curTop +2+'px';
    
    1. 让要操作的元素进行”离线处理“, 处理完后一起更新使用DocumentFragment进行缓存操作,引发一次回流和重绘. DocumentFragment 给我们带来的性能优化使用display:none技术,只引发两次回流和重绘;前面也提到,如果影响到页面布局就会导致回流 那么先把元素设置为 display:none 最后再 display:block 即可使用cloneNode(true or false) 和 replaceChild 技术,引发一次回流和重绘;