| 1.防抖

防抖,顾名思义就是防止用户“手抖”持续输出,把多次向服务器请求相同数据,把服务器干冒烟了。这时候我们需要设置“防抖”,“一个大招用后几秒后点击才能继续使用”。

image.png

应用场景:

输入框搜索建议:当用户输入时,防抖可以用于延迟发送请求,避免频繁请求后端接口。窗口大小调整:当窗口大小调整时,防抖可以用于调整事件触发的频率,避免频繁操作导致页面抖动。按钮防重复点击:当用户频繁点击按钮时,防抖可以用于限制按钮点击的频率,避免重复提交操作。

下面我用第一个(输入框搜索)应用场景,带着大家一步步手写“防抖”效果代码。

其中数据采用json-server 进行数据管理,创建后端user数据。如果不知道怎么创建环境,可以看看下面“浪遏”大佬这篇文章

{"users": [
    {
      "id": "1",
      "name": "史铁兵"
    },
    {
      "id": "2",
      "name": "刘红旗"
    },
    {
      "id": "3",
      "name": "张三"
    }
  ]
  }

下面没有使用防抖情况,实现用户输入,搜索请求后端数据

首先,我们在body创建搜索框,并且当地到监听事件,执行使用fetch从后端拉起数据,再使用filter过滤出对应includes数据,这里使用es6新增方法map 映射把用户姓名打印到页面。其中使用join转换成字符串。


    div>
        label for="unDebounceInput">用户搜索label>
        input type="text"
            id="unDebounceInput"
            placeholder="输入需要搜索的用名字">
    div>
    ul id="user">ul>
    script>
       const oUL = document.querySelector('#user');
       // reset api 接口 ,通往后端接口  fetch 函数
       const oInput = document.getElementById('unDebounceInput');
       // keyup 事件, 当用户输入时触发;事件处理函数,this指向oInput事件源
       oInput.addEventListener('keyup',function() {
        let val = this.value.trim();
        if(val == '') {
            oUL.innerHTML = '';return;// 清空ul
        }
         fetch('http://localhost:3001/users')
             .then(res => res.json())
             .then(user => {
                // 过滤用户,
                const result = user.filter(item => item.name.includes(this.value))
                // Array 在es6中新增的方法
                oUL.innerHTML = result.map(item => `
  • ${item.name}
  • `
    ).join('') }) })
    script> body>

    事件绑定keyup,不断向后端请求数据

    下面代码使用防抖,减少因为用户多次向服务器访问出现卡顿问题。封装函数debounceNameSearch,并且传入fn和定时时间1s。看下面代码:

        
    

    实现一下fn函数

    // fn 函数
           function fn() {
            let val = this.value.trim(); // 去除空格
            if(val == '') {
                oUL.innerHTML = '';return;// 清空ul
            }
            fetch('http://localhost:3001/users')
                 .then(res => res.json())
                 .then(user => {
                    // 过滤用户,
                    const result = user.filter(item => item.name.includes(this.value))
                    // Array 在es6中新增的方法
                    oUL.innerHTML = result.map(item => `
  • ${item.name}
  • `
    ).join('') }) }

    防抖节流js_如何实现防抖节流_

    主要看一下debounce代码:这里使用apply处理fn,处理this指向问题,不是指向window,指向oInput;使用类数组arguments。

     // defounce函数
             function debounce(fn,delay) {
                let timer = null;
                return function() {
                // 指定的时间后执行,使用类数组传递参数
                    timer = setTimeout(() => {
                         console.log(this);
                    },delay)
                }
             }
    

    在这段代码里面,使用debounce函数,通过传入fn ,delay作为参数,实现delay时间后,执行fn函数。我详细看看dedounce函数任何实现防抖。当用户输入值进行查询时候,调用debounce(fn,1000),增加1s后延迟实现fn调用,只有当用户不在输入后才执行需要的事件,这里就是fn()方法。

    这样直到用户输入完成1s后执行输出打印效果。这时候在debounce函数声明一个timer变量,用来记录定时器的名字,然后在返回函数中,我们将每次点击创建的定时器赋值给timer,所以我们只要在这之前判断timer是否有值,如果timer有值,说明上一次点击事件创建的定时器还没有执行完,所以这时我们只需把上次的定时器清空,则不会再执行上次的点击事件了,直到在延时时间内不再点击,则才会执行我们需要执行的事件。这时代码如下:

     // defounce函数
             function debounce(fn,delay) {
                let timer = null;
                return function() {
                    if(timer) {
                        clearTimeout(timer);// 清除定时器
                    }
                // 指定的时间后执行,使用类数组传递参数
                    timer = setTimeout(() => {
                        fn.apply(this,arguments)//
                    },delay)
                }
             }
    

    到这里我们的防抖代码就成功实现啦!这里面每一条代码都运用的非常巧妙,需要我们对闭包,this指向,以及第二种方法箭头函数的知识都要了解的非常清楚,知道了这些,是不是觉得手写防抖代码很简单啦~

    | 2.节流(Throttle)

    节流,通俗将就是一个事件持续发生,需要限制一个时间间隔执行。比如,王者荣耀开完大招,总是点击还是没有用,只有到一定时间后才可以发送。。下面是实现步骤流程图:

    image.png

    应用场景:

    页面滚动加载:当用户滚动页面时,节流可以用于限制加载事件的触发频率,避免过多的加载请求。频繁点击按钮:当用户频繁点击按钮时,节流可以用于限制按钮点击的频率,避免过于频繁的操作。

    
      button id="btn" class="btn">点击加载button>
      script>
        function fn() {
          console.log('Hello', this);
        }
        // 确保在 DOM 完全加载后获取元素
        document.addEventListener('DOMContentLoaded', (event) => {
          const btn = document.getElementById("btn");
          btn.addEventListener("click", throttle(fn, 1000));
        });
        function throttle(fn, limit) {
          let pretime = 0; // 初始化为 0
          return function() {
            const now = Date.now();
            if (now - pretime > limit) {
              fn()
              pretime = now;
            }
          };
        }
      script>
    
    

    通过使用Date.now()和now和限制时间进行计算,实现节流操作。

    image.png

    同样的使用apply让this从window指向btn

    function throttle(fn, limit) {
          let pretime = 0; // 初始化为 0
          return function() {
            const now = Date.now();
            if (now - pretime > limit) {
              fn.apply(this, arguments); // 使用 apply 方法确保 this 正确指向
              pretime = now;
            }
          };
        }
    

    这样虽然多次点击加载,但是还是在limit时间后执行一次事件

    总结

    防抖:在规定时间内,多次触发只响应最后一次。(多次触发,只执行最后一次)

    节流:在规定时间内,多次触发只响应第一次。(规定时间内,只触发一次)

    以上代码分别展示了防抖和节流的实现方式。我们可以根据实际需要选择防抖还是节流来优化事件触发的频率,提升用户体验。

    声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。