深入滚动事件

简介

1 .使用到滚动的场景

1 .懒加载
2 .loadmore
3 .affix.固定位置
4 .回到顶部

2 .HTML5标准.scroll事件是每帧触发一次

帧维度解析渲染过程

1 .浏览器渲染页面的renderer进程里面,涉及到两个进程.两个进程之间通过commit的消息保持同步
2 .Main进程:浏览器渲染的主要执行步骤.包含从js执行到Composite合成的一系列操作
3 .Compositor线程:接收用户的一些交互操作,比如滚动->唤醒进程进行操作->接收Main线程的操作结果->commit给真正把页面draw到屏幕上的GPU进程


正常的操作

丢帧的操作

主线程里的操作太多,耗时长,commit的时间被推迟.浏览器来不及间页面draw到屏幕上,就丢失了一帧
4 .Main线程完成最后之后,与Compositor线程使用commit进行通信,Compositor调起Compositor来处理页面
5 .页面Paint结束之后,这一帧就结束了.GPU进程里的GPU进程负责把Render进程操作好的页面,交由GPU内方法,由GPU把页面draw到屏幕上
6 .屏幕刷新,我们就在浏览器上看到了新页面

浏览器主要执行步骤

1 .JavaScript:包含与视觉变化效果相关的js操作.包括不限于:Dom更新,元素样式动态改变
2.Style:样式计算.浏览器根据css选择器计算哪些元素应该用哪些规则,然后间样式规则落实到每个元素上面,确定每个元素具体的样式
3 .Layout:布局.在知道每一个元素应用哪些规则后,浏览器即可开始计算他占据的空间大小以及在屏幕中的位置

1 .避免layout的操作,将DOM脱离文档流在对其进行操作,所有操作完毕之后再添加到文档流中,这样可以将重排以及重绘的次数降低到一次或两次
2 .display:none
3 .DocumentFragment
4 .将原始元素拷贝到一个脱离文档的节点中,修改这个副本,完成后替换掉原始元素

4 .Painting:绘制.绘制时填充像素的过程.涉及绘出文本,颜色,图像,边框和阴影.基本上包括元素的每个可视部分,绘制一般时在多个层上完成的.

1 .painting和draw的区别:paint是把内容填充到页面,而draw是把页面反映到屏幕上

5 .Composite:合成.由于页面的各部分可能被绘制到多层.因此他们还需要按照正确的顺序绘制到屏幕上,以便正确渲染页面.对于与另一个元素重叠的元素来说.这很重要,因为一个错误可能使另一个元素错误的出现在另一个元素上面
6 .并不是每次都会走到全部的流程.
7 .重排:会走完整的流程,改变了元素的几何属性(宽度,高度,左侧或者顶部位置等.必须检查所有的其他元素).任何受印象的部分都需要重新绘制.而且最终绘制的元素需要重新合成,重排进行了管道的每一步,性能受到很大的影响
8 .重绘:和上面相比不需要layout:如果是背景图片,文字颜色或者阴影的话,不会影响页面布局的属性,浏览器会跳过布局
9 .不重排和重绘的情况:仅仅使用transform和opacity来实现动画,会避免Layout和Paint操作
10 .每个层中对这个层进行 Layout 或者 Paint 是不会影响其他层的,一般会根据整个页面的语义将页面分为几个层。
11 .查询css属性变化导致的操作https://csstriggers.com/

优化操作

1 .避免在scroll事件中修改样式属性/将样式操作从scroll事件中剥离
1 .变量的初始化,不依赖滚动位置变化的计算都应该在scroll事件外提前就绪

2 .使用web worker分离和页面渲染无关的逻辑计算
3 .触发监听事件时使用函数节流或者去抖
4 .使用requestAnimationFrame提代定时器:浏览器每一次重回前触发这个钩子

1 .不要在 rAF 的回调函数中先修改样式,再查询样式,这样就失去了 rAF 的作用。可以将对样式的查询提前到回调函数中或者 rAF 中尽量靠前的位置
2 .动画是由浏览器按照一定的频率一帧一帧的绘制的,由css实现的动画的优势就是浏览器知道动画的开始及每一帧的循环间隔,能够在恰当的时间刷新UI,给用户一种流畅的体验,而setInterval或setTimeout实现的JavaScript动画就没有这么可靠了,因为浏览器压根就无法保证每一帧渲染的时间间隔,一般情况下,每秒平均刷新次数能够达到60帧,就能够给人流畅的体验,即每过 1000/60 毫秒渲染新一帧即可,但从上面的例子知,这一点单靠定时器是无法保证的。
为此,requestAnimationFrame应运而生,其作用就是让浏览器流畅的执行动画效果。可以将其理解为专门用来实现动画效果的api,通过这个api,可以告诉浏览器某个JavaScript代码要执行动画,浏览器收到通知后,则会运行这些代码的时候进行优化,实现流畅的效果,而不再需要开发人员烦心刷新频率的问题了
3 .requestAnimationFrame接受一个动画执行函数作为参数,这个函数的作用是仅执行一帧动画的渲染,并根据条件判断是否结束,如果动画没有结束,则继续调用requestAnimationFrame并将自身作为参数传入。从示例来看,得到了效果平滑流畅的动画,这样就巧妙地避开了每一帧动画渲染的时间间隔问题
function animationWidth() {
  var div = document.getElementById('box');
  div.style.width = parseInt(div.style.width) + 1 + 'px';

  if(parseInt(div.style.width) < 200) {
    requestAnimationFrame(animationWidth)
  }
}
requestAnimationFrame(animationWidth);

5 .requestIdleCallback():会在浏览器的每一帧末尾触发.而且是空闲的时候,如果不空闲,就推迟到下一帧.适合于执行在后台运行或者空闲时触发回调,否则推迟到下一帧.

避免强制重排:当我们很频繁的执行下面这样的特殊操作.就会打断浏览器的节奏

1 .当访问scrollWidth,clientWidth,offsetTop,computedStyle登属性时,会触发这个效果,导致style和layout前移到js代码执行过程中
2 .
elem.offsetLeft, elem.offsetTop, elem.offsetWidth, elem.offsetHeight, elem.offsetParent
elem.clientLeft, elem.clientTop, elem.clientWidth, elem.clientHeight
elem.getClientRects(), elem.getBoundingClientRect()
elem.scrollWidth, elem.scrollHeight
elem.scrollLeft, elem.scrollTop
//这里不是求当前div的滚动距离的操作么,这个也会造成重排么?
以上的特殊读操作,一定要使用requestAnimationFrame()包裹起来.避免单个裸奔

提升合成层

1 .一些属性会让元素们创建出不同的渲染层

1 .relative,fixed,sticky,absolute
2 .有透明度的属性
3 .css滤镜
4 .css transform属性

2 .达成一些条件,渲染条件会提升为合成层

1 .一键加速的iframe,iframe嵌入的页面中有合成层
2 .3D或者硬件加速的2dCanvas
3 .video元素
4 .3d transform
5 .will-change:设置为opacity,transoorm,top,left,bottom,
6 .对opacity,tramsform,filter,backgroundFilter应用了animation或者transition

3 .合成层之后,会交由GPU处理,比CPU处理快,但需要重绘的时候,只需要重绘自己的层,不会影响到其他的层

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353

推荐阅读更多精彩内容