滚动优化的由来

滚动优化其实也不仅仅指滚动(scroll 事件),还包括了例如 resize 这类会频繁触发的事件。

var i = 0;window.addEventListener('scroll',function(){console.log(i++);},false);

在绑定 scroll 、resize 这类事件时,当它发生时,它被触发的频次非常高,间隔很近。如果事件中涉及到大量的位置计算、DOM 操作、元素重绘等工作且这些工作无法在下一个 scroll 事件触发前完成,就会造成浏览器掉帧。加之用户鼠标滚动往往是连续的,就会持续触发 scroll 事件导致掉帧扩大、浏览器 CPU 使用率增加、用户体验受到影响。

在滚动事件中绑定回调应用场景也非常多,在图片的懒加载、下滑自动加载数据、侧边浮动导航栏等中有着广泛的应用。

当用户浏览网页时,拥有平滑滚动经常是被忽视但却是用户体验中至关重要的部分。当滚动表现正常时,用户就会感觉应用十分流畅,令人愉悦,反之,笨重不自然卡顿的滚动,则会给用户带来极大不舒爽的感觉。

   滚动与页面渲染的关系

为什么滚动事件需要去优化?因为它影响了性能。那它影响了什么性能呢?额......这个就要从页面性能问题由什么决定说起。

我觉得搞技术一定要追本溯源,不要看到别人一篇文章说滚动事件会导致卡顿并说了一堆解决方案优化技巧就如获至宝奉为圭臬,我们需要的不是拿来主义而是批判主义,多去源头看看。

从问题出发,一步一步寻找到最后,就很容易找到问题的症结所在,只有这样得出的解决方法才容易记住。

说教了一堆废话,不喜欢的直接忽略哈,回到正题,要找到优化的入口就要知道问题出在哪里,对于页面优化而言,那么我们就要知道页面的渲染原理:

浏览器渲染原理我在我上一篇文章里也要详细的讲到,不过更多的是从动画渲染的角度去讲的:【Web动画】CSS3 3D 行星运转 && 浏览器渲染原理 。

想了想,还是再简单的描述下,我发现每次 review 这些知识点都有新的收获,这次换一张图,以 chrome 为例子,一个 Web 页面的展示,简单来说可以认为经历了以下下几个步骤:

  • JavaScript:一般来说,我们会使用 JavaScript 来实现一些视觉变化的效果。比如做一个动画或者往页面里添加一些 DOM 元素等。

  • Style:计算样式,这个过程是根据 CSS 选择器,对每个 DOM 元素匹配对应的 CSS 样式。这一步结束之后,就确定了每个 DOM 元素上该应用什么 CSS 样式规则。

  • Layout:布局,上一步确定了每个 DOM 元素的样式规则,这一步就是具体计算每个 DOM 元素最终在屏幕上显示的大小和位置。web 页面中元素的布局是相对的,因此一个元素的布局发生变化,会联动地引发其他元素的布局发生变化。比如,<body> 元素的宽度的变化会影响其子元素的宽度,其子元素宽度的变化也会继续对其孙子元素产生影响。因此对于浏览器来说,布局过程是经常发生的。

  • Paint:绘制,本质上就是填充像素的过程。包括绘制文字、颜色、图像、边框和阴影等,也就是一个 DOM 元素所有的可视效果。一般来说,这个绘制过程是在多个层上完成的。

  • Composite:渲染层合并,由上一步可知,对页面中 DOM 元素的绘制是在多个层上进行的。在每个层上完成绘制过程之后,浏览器会将所有层按照合理的顺序合并成一个图层,然后显示在屏幕上。对于有位置重叠的元素的页面,这个过程尤其重要,因为一旦图层的合并顺序出错,将会导致元素显示异常。

这里又涉及了层(GraphicsLayer)的概念,GraphicsLayer 层是作为纹理(texture)上传给 GPU 的,现在经常能看到说 GPU 硬件加速,就和所谓的层的概念密切相关。但是和本文的滚动优化相关性不大,有兴趣深入了解的可以自行 google 更多。

简单来说,网页生成的时候,至少会渲染(Layout+Paint)一次。用户访问的过程中,还会不断重新的重排(reflow)和重绘(repaint)。

其中,用户 scroll 和 resize 行为(即是滑动页面和改变窗口大小)会导致页面不断的重新渲染。

当你滚动页面时,浏览器可能会需要绘制这些层(有时也被称为合成层)里的一些像素。通过元素分组,当某个层的内容改变时,我们只需要更新该层的结构,并仅仅重绘和栅格化渲染层结构里变化的那一部分,而无需完全重绘。显然,如果当你滚动时,像视差网站(戳我看看)这样有东西在移动时,有可能在多层导致大面积的内容调整,这会导致大量的绘制工作。

相对于解决高频率的触发事件,常用解决方式是防抖和节流。

防抖(Debouncing) 
防抖技术即是可以把多个顺序地调用合并成一次,即规定事件被触发的次数。

// 防抖动函数
function debounce(func, wait, immediate) {var timeout;return function() {var context = this, args = arguments;var later = function() {timeout = null;if (!immediate) func.apply(context, args);};var callNow = immediate && !timeout;clearTimeout(timeout);timeout = setTimeout(later, wait);if (callNow) func.apply(context, args);};
};var myEfficientFn = debounce(function() {// 滚动中的真正的操作
}, 250);// 绑定监听
window.addEventListener('resize', myEfficientFn);

节流函数即只允许函数在x毫秒内执行一次

// 简单的节流函数
function throttle(func, wait, mustRun) {var timeout,startTime = new Date();return function() {var context = this,args = arguments,curTime = new Date();clearTimeout(timeout);// 如果达到了规定的触发时间间隔,触发 handlerif(curTime - startTime >= mustRun){func.apply(context,args);startTime = curTime;// 没达到触发间隔,重新设定定时器}else{timeout = setTimeout(func, wait);}};
};
// 实际想绑定在 scroll 事件上的 handler
function realFunc(){console.log("Success");
}
// 采用了节流函数
window.addEventListener('scroll',throttle(realFunc,500,1000));

两者优缺点:

  • 防抖动:防抖技术即是可以把多个顺序地调用合并成一次,也就是在一定时间内,规定事件被触发的次数。

  • 节流函数:只允许一个函数在 X 毫秒内执行一次,只有当上一次函数执行后过了你规定的时间间隔,才能进行下一次该函数的调用。

文章转载自:http://www.cnblogs.com/coco1s/p/5499469.html

原作者:ChokCoco

高性能滚动scroll(防抖和节流)相关推荐

  1. 高性能滚动 scroll 及页面渲染优化

    最近在研究页面渲染及web动画的性能问题,以及拜读<CSS SECRET>(CSS揭秘)这本大作. 本文主要想谈谈页面优化之滚动优化. 主要内容包括了为何需要优化滚动事件,滚动与页面渲染的 ...

  2. 防抖 节流_每日一题手写函数防抖与节流

    关注"前端学苑" ,坚持每天进步一点点 「~函数防抖与节流 ~」 每日一题,希望让爱学习.思考的前端技术伙伴在一起学习.复盘.成长. 基础知识要夯实,原理源码要深入,深度广度要扩展 ...

  3. vue防抖和节流是什么_防抖和节流为什么重要!!!

    是什么 防抖和节流两者类似[但并不一样]是用来控制某一函数在特定时间内执行次数的技术点. 什么时候重要 在给Dom绑定事件的时候显得尤为重要,因为相当于在事件函数和Dom之间加了一层控制层. 为什么重 ...

  4. resize函数_每日一题手写函数防抖与节流

    关注"前端学苑" ,坚持每天进步一点点 「~函数防抖与节流 ~」 每日一题,希望让爱学习.思考的前端技术伙伴在一起学习.复盘.成长. 基础知识要夯实,原理源码要深入,深度广度要扩展 ...

  5. JavaScript防抖与节流的具体实现及使用场景

    文章目录 前言 一.什么是防抖和节流? 二.防抖 简单介绍 图解 代码如下(示例): 二.节流 简单介绍 图解 代码如下(示例): 三.防抖与节流的使用场景 总结 前言 最近遇到注册登陆按钮需要添加防 ...

  6. 一篇让你彻底明白防抖和节流以及应用场景

    1.谈一谈防抖与节流?有什么区别?如何实现? 定义 所谓防抖,就是指触发事件后,在 n 秒后函数才会执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间 所谓节流,就是指连续触发事件,但是在 ...

  7. 全网最详细JavaScript防抖、节流函数解析

    防抖与节流 防抖与节流 防抖 作用与简介 实现 核心与细节 应用场景 节流 作用与简介 实现 核心与细节 应用场景 防抖与节流 防抖 作用与简介 在一个周期T内,如果重复的进行某种响应操作,在不设置防 ...

  8. 什么是防抖和节流?有什么区别?

    一 . 防抖和节流是什么 本质上是优化高频率执行代码的一种手段 如:浏览器的 resize.scroll.keypress.mousemove 等事件在触发时,会不断地调用绑定在事件上的回调函数,极大 ...

  9. 防抖和节流 含义及区别图文详解秒懂

    防抖和节流都是为解决短时间内频繁触发某个功能函数而导致的性能问题.比如,触发频率过高而导致响应速度跟不上,以致出现延迟,假死或卡顿的现象. 防抖 图解:一件事情,计划5s以后触发,结果中途意外触发了, ...

最新文章

  1. UA MATH567 高维统计IV Lipschitz组合3 高斯分布的Lipschitz函数
  2. [bzoj2882]工艺_后缀数组
  3. mysql数据库提示2005_Mysql数据库从本地导出 服务器上导入时报 ERROR 2005 HY000 Unknown MySQL ser...
  4. 华为平板wps语音朗读_华为平板M6 10.8英寸综合评测 目前体验最好的安卓平板
  5. 浙大网新实训项目介绍
  6. Oracle定时器调用存储过程
  7. Windows10系统Python2.7通过Swig调用C++过程
  8. .net mvc中级联的使用
  9. 亿航智能⻓续航⻜机有望在4-8周内首⻜亮相
  10. CSS字体系列(CSS、HTML)
  11. 数据挖掘:特征提取——PCA与LDA
  12. IS-IS详解(十七)——IS-IS 区域迁移与路由汇总
  13. /bin/sh: 1: tclsh: not found
  14. mysql数据库文件结构同步,[数据库的表同步mysql]MySQL表结构同步
  15. 科研计算机视觉常用绘图软件,科研图形处理——除了R、Graphpad外,这款软件也不要错过哦!...
  16. zemax光学设计高阶优化
  17. 通过银行卡号查询银行卡类型接口
  18. 领导力21法则自测题
  19. @Autowired和@Resource区别
  20. jsp页面适应手机屏幕_JavaScript实现移动端页面按手机屏幕分辨率自动缩放的最强代码...

热门文章

  1. 第28件事 挖掘用户真实需求的6大撒手锏
  2. 如何 Scale Up/Down 应用?- 每天5分钟玩转 Docker 容器技术(126)
  3. 键入一个网页后了发生什么
  4. 策略模式/Strategy
  5. Static静态---笔记A
  6. GNU make manual 翻译(六十三)
  7. 说说我心中的Linux系统
  8. tornado框架hello world实践
  9. HTTP权威指南记录 ---- 网络爬虫
  10. Android 应用开机自启和无需权限开启悬浮框