zoukankan      html  css  js  c++  java
  • 防抖和节流

    防抖和节流是高频操作的优化方案,防抖是把连续的高频操作优化为最后一次操作(常用方案略有不同,此处仅介绍思路),节流是将高频操作降频,固定时间内执行一次。

    先通过触发浏览器的mousemove事件来介绍一下防抖和节流的实现:

     1 // html
     2 <body>
     3   <div id="content">0</div>
     4 </body>
     5 
     6 // js
     7 function count() {
     8     document.getElementById('content').innerHTML = Math.random().toFixed(6)
     9   }
    10 
    11   window.onmousemove = count

    在不使用防抖的情况下直接给window绑定事件,只要鼠标移动,事件会一直被触发。

    1.防抖debounce

    可以在事件被触发时不直接执行处理函数,而是设定一个计时器,事件(短时间内)再次被触发就重新开始计时,直到超过一定间隔后才执行函数。

     1 function debounce(func, wait) {
     2   let timeout
     3   return function () {
     4     if (timeout) {
     5       clearTimeout(timeout)
     6     }
     7     timeout = setTimeout(func, wait)
     8   }
     9 }
    10 window.onmousemove = debounce(count, 1000)

    查看完整版:

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4   <meta charset="UTF-8">
     5   <meta name="viewport" content="width=device-width, initial-scale=1.0">
     6   <title>Debounce</title>
     7   <style>
     8     *{
     9       margin: 0;
    10       padding: 0;
    11       border: 0;
    12     }
    13     #content{
    14       box-sizing: border-box;
    15       height: 100vh;
    16        100vw;
    17       padding-top: 60px;
    18       background-color: #87ceeb;
    19       font-size: 60px;
    20       text-align: center;
    21       color: #fff;
    22       overflow: hidden;
    23     }
    24   </style>
    25 </head>
    26 <body>
    27   <div id="content">0</div>
    28 </body>
    29 <script>
    30   function count() {
    31     document.getElementById('content').innerHTML = Math.random().toFixed(6)
    32     console.info(Math.random().toFixed(6))
    33   }
    34   // window.onmousemove = count
    35 
    36   // 防抖 - 超过时间间隔后触发一次处理函数
    37   function debounce(func, wait) {
    38     let timeout
    39     return function () {
    40       if (timeout) {
    41         clearTimeout(timeout)
    42       }
    43       timeout = setTimeout(func, wait)
    44     }
    45   }
    46   // window.onmousemove = debounce(count, 1000)
    47 
    48   // 防抖 - 先执行一次处理函数
    49   function debounceAdvance(func, wait) {
    50     let timeout
    51     return function () {
    52       let context = this
    53       let args = arguments
    54       if (timeout) {
    55         clearTimeout(timeout)
    56       }
    57       let callNow = !timeout
    58       timeout = setTimeout(() => {
    59         timeout = null
    60         func.apply(context, args)
    61       }, wait)
    62       if (callNow) {
    63         func.apply(context, args)
    64       }
    65     }
    66   }
    67   window.onmousemove = debounceAdvance(count, 500)
    68 </script>
    69 </html>
    View Code

    2.节流throttle

    节流是把高频操作降低到一段时间内(delay)执行一次,可以在第一次出发时创建一个时间戳prev,和再次触发事件的时间戳now比较,如果间隔大于delay就触发事件,重新计时

     1 // 时间戳版
     2 let throttle = function(func, delay){
     3   let prev = Date.now()
     4   return function() {
     5     let now = Date.now()
     6     if(now - prev >= delay){
     7       func()
     8       prev = Date.now()
     9     }
    10   }
    11 }
    12 window.onmousemove = throttle(handle, 1000)

    或者使用定时器完成,完整版:

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4   <meta charset="UTF-8">
     5   <meta name="viewport" content="width=device-width, initial-scale=1.0">
     6   <title>Throttle</title>
     7   <style>
     8     *{
     9       margin: 0;
    10       padding: 0;
    11       border: 0;
    12     }
    13     #content{
    14       box-sizing: border-box;
    15       height: 100vh;
    16        100vw;
    17       padding-top: 60px;
    18       background-color: #87ceeb;
    19       font-size: 60px;
    20       text-align: center;
    21       color: #fff;
    22       overflow: hidden;
    23     }
    24   </style>
    25 </head>
    26 <body>
    27   <div id="content">0</div>
    28 </body>
    29 <script>
    30   function handle() {
    31     document.getElementById('content').innerHTML = Math.random().toFixed(6)
    32     console.info(Math.random().toFixed(6))
    33   }
    34   // window.onmousemove = handle
    35 
    36   // 时间戳版
    37   let throttle = function(func, delay){
    38     let prev = Date.now()
    39     return function() {
    40       let now = Date.now()
    41       if(now - prev >= delay){
    42         func()
    43         prev = Date.now()
    44       }
    45     }
    46   }
    47   // window.onmousemove = throttle(handle, 1000)
    48 
    49   // 定时器版
    50   let throttle2 = function(func, wait){
    51     let timeout
    52     return function() {
    53       if(!timeout){
    54         timeout = setTimeout(()=>{
    55           func()
    56           timeout = null
    57         }, wait)
    58       }
    59     }
    60   }
    61  
    62   window.onmousemove = throttle2(handle, 1000)
    63 
    64 </script>
    65 </html>
    View Code

    3.应用场景

    常用于用户不断改变浏览器大小、鼠标移动和输入验证的一些处理,这些最后触发一次的使用防抖即可;

    鼠标不断点击、鼠标滚动不断加载等适合使用节流throttle.

    说下我的案例:

    一个数据在线编辑平台,用户需要不断输入X、Y、Z坐标调整物体位置,希望不用离开输入框就能实时看到变化,如果监听keyup事件就会过于频繁,这时就适合使用防抖。

    另外一个是在地图中加载了20w+模型,每次移动地图都会触发模型的重新渲染,这是就需要再地图的move事件中进行一些干预,可以用防抖,不过幸运的是地图有moveend事件,也算是一种防抖吧。

  • 相关阅读:
    使用Entity Framework时要注意的一些性能问题
    在EntityFrameWork中定义值对象的注意事项
    关于EntityFrameWork中的贪婪加载和延时加载
    Centos上安装mplayer
    Centos上安装madplay
    编译可加载lcd驱动的linux uImage
    ok6410上移植madplay
    linux上安装Qt
    ok6410的mplayer移植
    交叉编译tslib
  • 原文地址:https://www.cnblogs.com/jyughynj/p/13438641.html
Copyright © 2011-2022 走看看