JavaScript/VUE 手写防抖节流

防抖

定义

指触发事后在 n 秒内函数只执行一次,若在 n 秒内再次触发则重新计算

手写源码

案例一

<button id='btn'>防抖提交</button>

<script>
    function success(e){
        console.log('提交成功')
    }

    //防抖函数
    function debounce(callback,delay=200){
        let timer = null
		return function()=>{
            clearTimeout(timer)
			timer = setTimeout(()=>{
				callback.apply(this, arguments)
			},delay)
		}
    }

    const oDebounce = debounce(success,1000)

    const btn = document.querySelector('#btn')
    btn.addEventListener('click',oDebounce)
</script>

案例二

<button id="btn">按钮</button>
<script>
    function debounce(callback, delay = 200,...args) {
        let timer = null
        return () => {
            clearTimeout(timer)
            timer = setTimeout(() => {
                callback.apply(this, args)
            }, delay)
        }
    }

    function f1(a) {
        console.log(a)
    }
    const btn = document.querySelector('#btn')

    btn.onclick = debounce(f1, 200,1)
</script>
Vue 中使用防抖
export function debouce(callback, delay = 400) {
	let last = 0;
	let timer = null;
	return function () {
		if (timer) clearTimeout(timer);
		const now = +new Date();
		if (now - last > delay) {
			clearTimeout(timer);
			timer = setTimeout(() => {
				callback.apply(this, arguments);
				last = now;
			}, delay);
		} else {
			last = now;
			callback.apply(this, arguments);
		}
	};
}

export default {
    data() {
   	 	return {
    		keyword: "",
    	};
    },
    methods: {
        /* 搜素 */
        toSearch: debouce(function(e){
    		console.log(this.keyword)
        }, 500),
    },
};

<!-- 滑动案例 -->
<template>
  <div class="home">
  </div>
</template>

<script>

export default {
  name: 'Home',
  data() {
    return {
      showInput:false
    }
  },
  mounted(){
    window.addEventListener('scroll',this.debouce(this.scroll,400))
  },
  destroyed(){
    window.removeEventListener('scroll')
  },
  methods:{
    scroll(){
      console.log('页面滚动了')
    },
    debouce(callback,delay=400){
      let timer = null
      return ()=>{
        if(timer) clearTimeout(timer)
        timer = setTimeout(()=>{
          callback.apply(this,arguments)
        },delay)
      }
    }
  }
}
</script>

<style scope>
  .home{
    height: 200vh;
    width: 100vw;
  }
</style>
=================================
<!-- 按钮案例 -->

<template>
  <div class="home">
    <button @click="debounce(handleClick)">按钮</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      timer:null
    };
  },
  methods: {
    handleClick() {
      console.log("页面滚动了");
    },
    debounce(callback,delay=400){
      if(this.timer) clearTimeout(this.timer)
      this.timer = setTimeout(()=>{
        callback.apply(this,arguments)
      },delay)
    },
    // 用 return 返回,使用时要用 debouceFN(handleClick,200)()
    debouceFN(callback, delay = 400,...args) {
      return function () {
        if (this.timer) clearTimeout(this.timer);
        this.timer = setTimeout(() => {
          callback.apply(this, args);
        }, delay);
      };
    },
    //
    betterDebouce(callback, delay = 400) {
        let last = 0;
        let timer = null;
        return function () {
            if (timer) clearTimeout(timer);
            const now = +new Date();
            if (now - last > delay) {
                clearTimeout(timer);
                timer = setTimeout(() => {
                    callback.apply(this, arguments);
                    last = now;
                }, delay);
            } else {
                last = now;
                callback.apply(this, arguments);
            }
        };
    }
  }
};
</script>

节流

定义

连续发生的事件在 n 秒内只执行一次函数

手写源码
<button id='btn'>节流提交</button>

<script>
    function success(e){
        console.log('提交成功')
    }

    //节流函数
    function throttle(callback,delay=200){
        let flag = true
		return function()=>{
            if(!flag) return
            flag = false
			setTimeout(()=>{
				callback.apply(this,arguments)
                flag = true
			},delay)
		}
    }

    const oThrottle = throttle(success,1000)

    const btn = document.querySelector('#btn')
    btn.addEventListener('click',oThrottle)
</script>
在 vue 中使用节流
<template>
  <div class="home">
  </div>
</template>

<script>

export default {
  mounted(){
    window.addEventListener('scroll',this.throttle(this.scroll,1000))
  },
  destroyed(){
    window.removeEventListener('scroll',this.scroll)
  },
  methods:{
    scroll(){
      console.log('页面滚动了')
    },
    throttle(callback,interval=1000){
      let last = 0
      return ()=>{
        const now = +new Date()
        if((now - last)>interval){
          last = now
          callback.apply(this,arguments)
        }
      }
    }
  }
}
</script>

<style scope>
  .home{
    height: 200vh;
    width: 100vw;
  }
</style>
===================================

<template>
  <div class="home">
    <button @click="throttle(handleClick)">按钮</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      last: 0
    };
  },
  methods: {
    handleClick() {
      console.log("页面滚动了");
    },
    throttle(callback, interval = 1000) {
      const now = +new Date();
      if ((now - this.last) > interval) {
        this.last = now;
        callback.apply(this, arguments);
      }
    }
  }
};
</script>

======================================= 测试优化

export function throttle(callback,interval=1000){
  let last = 0
  return function(){
    const now = +new Date()
    if((now - last)>interval){
      last = now
      this[callback]()
    }
  }
}

亦或者是 
export function throttle(callback,interval=500){
  let flag = true
  return function() {
    if(!flag) return
    flag = false
    setTimeout(()=> {
        flag = true
        this[callback]()
    }, interval)
  }
}

<script>
	tipsearch: throttle('test'),
  async test() {
        if(!this.words) return
        const data = await get('/search', {
          keyword: this.words
        })
        console.log(data);
   },
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值