防抖和节流

135 阅读2分钟
/*  
 * 防抖函数 
 * 在规定的时间内,频繁的操作执行函数(例如用户点击多次按钮),只执行第一次或者最后一次(防止函数在没执行完的情况下,多次被触发) 
 * 参数 func  执行函数 
 *      wait  规定的之间内 
 *      immediate  判断执行第一次或最后一次   
*/
let fnDebounce = function fnDebounce(func,wait,immediate){    
    // 判断传入值的变量问题 start    
    if(typeof func !== 'function') throw new TypeError('func must be a function')    
    if(typeof wait === 'undefined'){        
        wait = 500;        
        immediate = false;    
    }    
    if(typeof wait === 'boolean'){        
         wait = 500;        
         immediate = wait;    
    }    
    if(typeof wait !== 'number')throw new TypeError('wait must be a number')    
    if(typeof immediate !== 'boolean')throw new TypeError('immediate must be a boolean')   
    // 判断传入值的变量问题 over    
    var timer = null,result;    
    return function proxy () {        
         var self  =this, params=[].slice.call(arguments),            
             callNow = !timer && immediate;        
             if(timer) clearTimeout(timer);        
         timer = setTimeout(function(){            
             clearTimeout(timer);            
             timer = null;            
             if(!immediate) result = func.apply(self,params);        
         },wait)        
         if(callNow) result = func.apply(self,params);        
         return result;    
    }
}

js中使用

<div id="app">        
    <button id="submit" onclick="fnTest()">防抖测试</button>    
</div>    
<script src="./untis.js"></script>    
<script>        
    let fnButton = function fnButton(){            
                       console.log('执行函数')       
                   }        
    let submit = document.getElementById('submit');        
    // submit.onclick = fnDebounce(fnButton,500,true);        
    // submit.addEventListener('click',fnDebounce(fnButton,500,true))        
    fnTest = fnDebounce( fnButton, 500, true);    
</script>

vue中使用

<template>  
    <div id="app">    
        <!-- 防抖测试 -->    
        <button @click="fnTest">防抖测试</button>  
    </div>
</template>
<script>
import utils from './units/index';
export default {  
    methods:{      
        fnTest(){        
            this.fnButton();     
        },      
        fnButton: utils.fnDebounce(function() {                     console.log('执行函数')      
        },500),  
    }
}
</script>

react中使用

import React from 'react';
import { withRouter } from 'react-router-dom';
import { connect } from "react-redux";
import { Button, Form } from 'antd';
const FormItem = Form.Item;
import  units  from './units.js';
class test extends React.Component {      
    fnTest = units.fnDebounce(function(){        
        console.log('执行函数')    
    },500,true)    
    render() {        
        return (            
             <div className="content_library flex" >                
                 <Button onClick={this.fnTest.bind(this)} >防抖测试</Button>            
             </div>        
        )    
    }
}
test = Form.create()(test);
function select(state) {    return {    };}
export default withRouter(connect(select)(test));

节流(使用方法同防抖)

/* 
  * 节流函数 
  * 在频繁的操作情况下,每隔指定的时间段,去执行函数 
  * 参数 func  执行函数 
  *      wait  规定的之间内 
*/
function fnThrottle(func, wait){    
    if(typeof func !== 'function') throw new TypeError('func must be a function')    
    // wait 转为数字    
    wait = +wait;    
    // 不是时间,默认给 300    
    if (isNaN(wait)) wait = 300;    
    var timer = null,        
        previous = 0,        
        result;    
    return function proxy() {        
        var self = this,            
            params = [].slice.call(arguments);        
            var now = +new Date,            
            // 剩下等待执行的时间            
            remaining = wait - (now - previous);         
            if(remaining <= 0) {            
                // 两次间隔时间已经超过WAIT了,此时我们立即执行            
                previous = now;            
                result = func.apply(self, params);            
                return result;        
             }        
             // 没有定时器我们才设置,有定时器说明上次还没执行呢,只有上次执行了,我们才开启下一次        
             if(!timer) {            
                 timer = setTimeout(function(){                
                      clearTimeout(timer);                
                      timer = null;                
                      previous = +new Date;                
                      result = func.apply(self, params);            
                 },remaining);        
              }        
              return result;    
      }
}