防抖
定义
指触发事后在 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>