前端防抖和节流

前端防抖和节流

概述

防抖: 防止抖动,个人字面理解此处防的不是页面的抖动,而是用户手抖。为了防止用户快速且频繁的触发事件而导致多次执行事件函数,这样的场景有很多,比如监听滚动、鼠标移动事件onmousemove、频繁点击表单的提交按钮等等。
节流: 节约流量,为了节约流量,页面在一个时间周期内,只触发一次动作。所以节流的目的时稀释函数的执行频率。
防抖动和节流本质是不一样的。防抖动是多次触发但只会执行一次,节流是多次触发但周期内只会执行一次

防抖实现

<html>

<body>
    <input type="button" id = "btn" value="提交" />
    <ul id="result"></ul>
    <script>

        var resultText = ""
        const print = (text) => {
            let item = document.createElement('li')
            item.innerText = text
            document.getElementById("result").appendChild(item)
        }
        // 创建debounce防抖函数
        const debounce = (func, wait) => {
            let timeout = null;
            // 此时func的this指向是window
            // 如果func内部想修改this指向当前函数的调用者,就必须存储this,之后借助apply修改func的this指向。
            // 因此借助闭包缓存调用者的this
            let context = null; 
            
            let args = null;
            // 通过定时器延迟执行事件函数
            let run = () => {
                timeout = setTimeout(() => {
                    // 通过 apply 修改func的this指向,并让func获取真正的事件函数(即防抖函数return出来的函数)的参数,之后执行func
                    func.apply(context, args);
                    timeout = null
                }, wait);
            }

            // 清除定时器
            let clean = () => {
                clearTimeout(timeout);
            }

            return function () {
                context = this; // 谁调用函数(这里的函数是防抖函数return出来的函数),this就指向谁。
              
                args = arguments; // arguments 是一个对应于传递给函数的参数的类数组对象,可以获取函数的参数(这里的函数是防抖函数return出来的函数)。
                console.log(args)
                if (timeout) {
                    print('重置定时器');
                    clean();
                    run();

                } else {
                    print('开启新的定时器');
                    run();
                }
            }
        }

        // 要执行的事件函数
        const handleSubmit = (e) => {
            print('提交表单', e);
        }

        const fn1 = debounce(handleSubmit, 1500)

        document.getElementById("btn").addEventListener("click", fn1)
    </script>
</body>

</html>

节流实现

<html>

<body>
    <input type="button" id="btn" value="提交" />
    <ul id="result"></ul>
    <script>

        var resultText = ""
        const print = (text) => {
            let item = document.createElement('li')
            item.innerText = text
            document.getElementById("result").appendChild(item)
        }
        const throttle = (func, wait) => {

            let timeout = null;

            return function () {
                let context = this;
                let args = arguments;
                if (!timeout) {
                    timeout = setTimeout(() => {
                        timeout = null;
                        func.apply(context, args);
                    }, wait)

                }
            }
        }

        // 要执行的事件函数
        const handleSubmit = (e) => {
            print('提交表单', e);
        }

        const fn1 = throttle(handleSubmit, 1500)

        document.getElementById("btn").addEventListener("click", fn1)
    </script>
</body>

</html>

你可能感兴趣的:(前端,前端)