防抖和节流

前言

前端的应用场景中,当某事件被触发则执行回调函数,如果不进行防抖和节流,浏览器的一些事件,如:resize,scroll,keydown,keyup,keypress,mousemove等。这些事件触发频率太过频繁,绑定在这些事件上的回调函数会不停的被调用。这样浏览器的目的是为了保证信息的一致性,而对于我们来说就是一种资源的浪费了。   

防抖的原理:事件响应函数在一段时间后执行;如果在规定时间内触发,则重新计算执行时间;当在一段时间内没有再次调用该函数,则立即执行该函数。

这个处理是基于DOM操作是十分巨大的开销。所以如果实际的代码中的回调函数只是处理一些js的数据,那么用不用防抖和节流处理是一样的。

正文

封装两个函数分别实现防抖和节流:

debounce:防抖,作用是在让在用户动作停止后延迟x ms再执行回调。 
throttle:节流,作用是在用户动作时每隔一定时间(如300ms)执行一次回调。 

下面以一个dom元素的onmousemove事件来举例说明:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style type='text/css'>
        #content-main {
            width: 100%;
            height: 360px;
            background: green;
            text-align: center;
            color: aliceblue;
            line-height: 360px;
            cursor: pointer;
        }
    </style>
    <script>
        var i = 0;
        window.onload = function () {
            /*防抖测试*/
            var doCallBack = debounce(callback, 2000);
            document.querySelector('#content-main').onmousemove = doCallBack;
            /*停止延迟事件的回调*/
            document.querySelector('#cancel').onclick = function () {
                doCallBack.cancel();
            }
            /*节流测试
            var doCallBack = debounce(callback, 2000);
            document.querySelector('#content-main').onmousemove = doCallBack;
            */
        }
        function debounce(func, wait, immediate) {
            var timeout, result;
            var debounced = function () {
                var slf = this;
                var callback_args = arguments;
                clearTimeout(timeout);
                if (immediate) {
                    var callnow = !timeout;
                    timeout = setTimeout(function () {
                        timeout = null;
                    }, wait);
                    if (callnow) result = func.apply(slf, callback_args);
                } else {
                    timeout = setTimeout(function () {
                        func.apply(slf, callback_args);
                    }, wait);
                }
                return result;
            }
            debounced.cancel = function () {
                clearTimeout(timeout);
            }
            return debounced;
        }

        function throttle(func, wait,options) {
            var old = 0;
            var timeout;
            if(!options) options={};
            return function () {
                var slf = this;
                var callback_args = arguments;
                var now = new Date().valueOf();
                if (options.leading == false && !old) {
                    old = now;
                }
                if (now - old > wait) {
                    if (timeout) {
                        clearTimeout(timeout);
                        timeout = null;
                    }
                    func.apply(slf, callback_args);
                    old = now;
                }
                else if (!timeout && options.trailing != false) {
                    timeout = setTimeout(function () {
                        func.apply(slf, callback_args);
                    }, wait);
                }
            }
        }

        function callback(arguments) {
            this.innerHTML = 'count:' + (++i);
            console.log(this);
            console.log(arguments);
        }
    </script>
</head>

<body>
    <div id='content-main'>鼠标移动到此区域,触发该区域的onmousemove事件</div>
    <!--用于防抖测试时,停止延迟事件的回调-->
    <button id='cancel'>取消</button>
</body>

</html>

 

 

posted @ 2020-06-09 00:17  灵风雨  阅读(107)  评论(0编辑  收藏  举报