美文网首页工作生活
请手写去抖和节流两个通用函数

请手写去抖和节流两个通用函数

作者: LeoMelody | 来源:发表于2019-07-03 01:34 被阅读0次

    这篇文章是手写实现xxx功能部分的第二篇,后续会陆续更新其他的。

    目录传送门 github地址

    考察点: 去抖和节流的理解以及应用场景

    去抖和节流

    去抖和节流是前端非常常用的工具方法。去抖可以保证一个操作不会不停地触发而节流可以保证在一段时间内一个操作只能触发一次。

    节流应用场景

    节流应用场景最多就是页面上的事件处理了。比如鼠标滑动事件的监听,页面滚动事件的监听等等。

    这里就拿页面滚动这个例子来说。这里我们实现一个常见的读书的那种web页面的头部导航条。效果可以看这里

    相应实例代码:

    // HTML
    <body>
      <div id="nav"></div>
      <div id="wrap"></div>
    </body>
    // CSS
    #wrap {
          background: red;
          width: 300px;
          height: 3300px;
          margin: 0 auto;
        }
    
        #nav {
          height: 10px;
          background: greenyellow;
          position: fixed;
          top: 0;
          left: 0;
          width: 1px;
        }
    // JS
    ;(function() {
      // 获取屏幕高度和宽度 之所以用这个高度,是因为这个height = screenHeight + 滚动到底部是的window.scrollY
      // 计算出可滚动的高度
      const height = document.documentElement.scrollHeight
      const width = document.documentElement.scrollWidth
      const screenHeight = document.documentElement.clientHeight
      const scrollHeight = height - screenHeight
      const nav = document.querySelector('#nav')
      window.addEventListener('scroll', function(e) {
        let currentHeight = window.scrollY
        nav.style.width = currentHeight/scrollHeight * width + 'px'
      })
    })()
    

    但是这种实现方式会非常频繁的修改DOM,这时候节流函数就体现处它的价值了。在这里,我直接就写节流函数的通用方法

    // 节流函数
    const throttle = function(fn, timer = 500) {
      let setTimeoutTimer 
      return function() {
        if (setTimeoutTimer) return 
       // 这行代码是为了方便在Vue这类框架中使用节流函数 
        fn && fn.call(this, ...arguments)
        setTimeoutTimer = setTimeout(() => {
          setTimeoutTimer = null
        }, timer)
      }
    }
    
    // 用法:将触发时间修改为50ms触发一次
    window.addEventListener('scroll', throttle(function(e) {
        let currentHeight = window.scrollY
        nav.style.width = currentHeight/scrollHeight * width + 'px'
      }, 50))
    

    效果

    上面还有提到在Vue这类框架中用到这个节流函数的用法,我用setInterval模拟事件触发,一个简单的demo

    let vue = {
      data: {
        name: 'wyh'
      },
      say(x) {
        console.log(this.data.name + x)
      }
    }
    
    let fn = throttle(vue.say, 500)
    
    setInterval(() => {
      fn.call(vue, 'x')
    }, 100)
    

    去抖应用场景

    个人认为去抖在平常开发中要用的更多,最常见的场景就是动态输入搜索(类似百度)这类功能的开发。这里就不做无去抖的效果展示了

    去抖通用函数

    function debounce(fn, timer = 500) {
      let debounceTimer
      return function() {
        if (debounceTimer) {
          clearTimeout(debounceTimer)
        }
        // 参数缓存
        let args = arguments
        debounceTimer = setTimeout(() => {
          fn && fn.call(this, ...args)
        }, timer)
      }
    }
    

    实例场景

    // html
    <input type="text" id="input" />
    // javascript
    ;(function() {
      const i = document.querySelector('#input')
      // 模拟Vue环境
      let vue = {
        data: {
          searchStr: ''
        },
        /**
         * 模拟搜索方法
         */
        search() {
          console.log(`正在以${this.data.searchStr}为检索值进行搜索`)
        } 
      }
      let searchFn = debounce(vue.search)
      i.addEventListener('input', function(e) {
        // 模拟v-model
        vue.data.searchStr = i.value
        searchFn.call(vue)
      })
    })()
    

    效果 记得打开下面的console看

    相关文章

      网友评论

        本文标题:请手写去抖和节流两个通用函数

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