美文网首页
前端性能优化之防抖节流

前端性能优化之防抖节流

作者: hjwang1024 | 来源:发表于2020-03-28 11:31 被阅读0次

    以 chrome 为例子,一个 Web 页面的展示,简单来说可以认为经历了以下下几个步骤:

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

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

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

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

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

    防抖(Debouncing)和节流(Throttling)

    • 防抖技术即是可以把多个顺序地调用合并成一次,也就是在一定时间内,规定事件被触发的次数。
      一个简化的例子:
    // 简单的防抖动函数
    function debounce(func, wait, immediate) {
        // 定时器变量
        var timeout;
        return function() {
            // 每次触发 scroll handler 时先清除定时器
            clearTimeout(timeout);
            // 指定 xx ms 后触发真正想进行的操作 handler
            timeout = setTimeout(func, wait);
        };
    };
    // 实际想绑定在 scroll 事件上的 handler
    function realFunc(){
        console.log("Success");
    }
    // 采用了防抖动
    window.addEventListener('scroll',debounce(realFunc,500));
    // 没采用防抖动
    window.addEventListener('scroll',realFunc);
    
    • 封装:
    // 防抖动函数
    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);
    
    • 有时候,我们希望即使页面在不断被滚动,但是滚动 handler 也可以以一定的频率被触发(譬如 250ms 触发一次),这类场景,就要用到另一种技巧,称为节流函数(throttling)。
    • 节流函数,只允许一个函数在 X 毫秒内执行一次。
    • 与防抖相比,节流函数最主要的不同在于它保证在 X 毫秒内至少执行一次我们希望触发的事件 handler。
    • 与防抖相比,节流函数多了一个 mustRun 属性,代表 mustRun 毫秒内,必然会触发一次 handler ,同样是利用定时器,看看简单的示例:
    // 简单的节流函数
    function throttle(func, wait, mustRun) {
        var timeout,
            startTime = new Date();
     
        return function() {
            var context = this,
                args = arguments,
                curTime = new Date();
     
            clearTimeout(timeout);
            // 如果达到了规定的触发时间间隔,触发 handler
            if(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));
    

    转自:https://www.cnblogs.com/coco1s/p/5499469.html

    相关文章

      网友评论

          本文标题:前端性能优化之防抖节流

          本文链接:https://www.haomeiwen.com/subject/hryjuhtx.html