本页二维码,扫一扫分享到朋友圈
朋友圈

浏览器高性能滑动解决方案(javascript)


阅读166 评论0 赞 46返回首页    go 编程与技术  go javascript


前言

最近一段时间,在项目中实现过瀑布流、懒加载、侧边栏导航等功能。总觉得在处理浏览器scroll滑动的时候有点问题,通过计算各个模块的高度和某些指定模块的出现时机时,在PC端还好,在移动端容易出现卡顿和抖动的情况。特此整理解决方案。


在停止滑动后执行

如果我们需要在滑动的时候进行某些操作,可以在停止滑动后再延迟进行,这样就不会一边滑动一边执行了。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

//滑动停止后延迟wait毫秒后才执行func

functiondebounce(func, wait){

// 定时器变量

vartimeout;

returnfunction(){

// 每次触发 scroll handler 时先清除定时器

clearTimeout(timeout);

// 指定 xx ms 后触发真正想进行的操作 handler

timeout = setTimeout(func, wait);

};

};

// 实际想绑定在 scroll 事件上的处理函数

functionrealFunc(){

console.log("Success");

}

// 采用了防抖动

window.addEventListener('scroll',debounce(realFunc,500));

// 没采用防抖动

//window.addEventListener('scroll',realFunc);

还可以更好的封装一番:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

// 防抖动函数

functiondebounce(func, wait, immediate){

vartimeout;

returnfunction(){

varcontext =this, args =arguments;

varlater =function(){

timeout =null;

if(!immediate) func.apply(context, args);

};

varcallNow = immediate & !timeout;

clearTimeout(timeout);

timeout = setTimeout(later, wait);

if(callNow) func.apply(context, args);

};

};

varmyEfficientFn = debounce(function(){

// 滚动中的真正的操作

},250);

// 绑定监听

window.addEventListener('scroll', myEfficientFn);


节流,在滑动中间隔执行

如果我们不是在滑动停止后执行,而是在滑动中需要实时计算一些东西,就可以采用节流的方式。

节流函数,只允许一个函数在 X 毫秒内执行一次。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

// 简单的节流函数

functionthrottle(func, wait, mustRun){

vartimeout,

startTime =newDate();

returnfunction(){

varcontext =this,

args =arguments,

curTime =newDate();

clearTimeout(timeout);

// 如果达到了规定的触发时间间隔,触发 handler

if(curTime - startTime >= mustRun){

func.apply(context,args);

startTime = curTime;

// 没达到触发间隔,重新设定定时器

}else{

timeout = setTimeout(func, wait);

}

};

};

// 实际想绑定在 scroll 事件上的 handler

functionrealFunc(){

console.log("Success");

}

// 采用了节流函数

window.addEventListener('scroll',throttle(realFunc,500,1000));

如果在一段时间内 scroll 触发的间隔一直短于 500ms ,那么能保证事件我们希望调用的 handler 至少在 1000ms 内会触发一次。


高精度控制

上面的两种方式都是通过setTimeout来实现的,精度不够高,如果对浏览器兼容性要求不高,或者是移动端web,可以使用原生的requestAnimationFrame来实现。

该方法的原理:在浏览器的页面重绘之前,通知浏览器调用一个指定的函数。该方法被调用的频率为每秒60次。

所以说用该方法来触发滚动事件,相当于上面的:

1

2

throttle(func, xx,1000/60)//xx 代表 xx ms内不会重复触发事件 handler

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

varticking =false;// rAF 触发锁

functiononScroll(){

if(!ticking) {

requestAnimationFrame(realFunc);

ticking =true;

}

}

functionrealFunc(){

// do something...

console.log("Success");

ticking =false;

}

// 滚动事件监听

window.addEventListener('scroll', onScroll,false);

这样浏览器就会以16.7ms的频率触发事件。


至于移动端,最好还是使用iscroll这样的模拟事件滑动的库来解决其延迟问题吧。


  上一篇:go 异步加载javascripot脚本解决方案
  下一篇:go javascript的api设计技巧


评论


用QQ登录管理/创建网站 用微博登录管理/创建网站   发布于:11-19