前端开发中我们经常会通过监听某些事件来完成项目需求
1.通过监听 scroll 事件,检测滚动位置,根据滚动位置显示返回顶部按钮
2.通过监听 resize 事件,对某些自适应页面调整DOM的渲染(通过CSS实现的自适应不再此范围内)
3.通过监听 keyup 事件,监听文字输入并调用接口进行模糊匹配
scroll事件
window.onscroll = function () {
//滚动条位置
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
}
从效果上,我们可以看到,在页面滚动的时候,会在短时间内触发多次绑定事件。
我们知道DOM操作是很耗费性能的,如果在监听中,做了一些DOM操作,那无疑会给浏览器造成大量性能损失。
下面我们进入主题,一起来探究,如何对此进行优化。
防抖:
通俗理解就是:延时处理,然后如果在这段延时内又触发了事件,则重新开始延时。
原理:对处理函数进行延时操作,若设定的延时到来之前,再次触发事件,则清除上一次的延时操作定时器,重新定时。
防抖实例:
let timer
window.onscroll=function(){
if(timer){
clearTimeout(timer)
}
timer=setTimeout(function(){
//滚动位置
let scrollTop=document.body.scrollTop|| document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop)
timer=undefined
},200)
}
实例效果:
函数封装:
/**
* 防抖函数
* @param method 事件触发的操作
* @param delay 多少毫秒内连续触发事件,不会执行
* @returns {Function}
*/
function debounce(method,delay) {
let timer = null;
return function () {
let self = this,
args = arguments;
timer && clearTimeout(timer);
timer = setTimeout(function () {
method.apply(self,args);
},delay);
}
}
window.onscroll = debounce(function () {
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
},200)
节流:
定义:触发函数事件后,短时间间隔内无法连续调用,只有上一次函数执行后,过了规定的时间间隔,才能进行下一次的函数调用。
原理:对处理函数进行延时操作,若设定的延时到来之前,再次触发事件,则清除上一次的延时操作定时器,重新定时。
let startTime =Date.now();//开始时间
let time =500;//间隔时间
let timer;
window.onscroll = function throttle(){
let currentTime=Date.now();
if(currentTime - startTime >= time){
let scrollTop = document.body.scroll||document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
startTime = currentTime;
}else{
clearTimeout(timer);
timer=setTimeout(function(){
throttle()
},50)
}
}
实例效果:每隔500毫秒触发一次事件
函数封装:
/**
* 节流函数
* @param method 事件触发的操作
* @param mustRunDelay 间隔多少毫秒需要触发一次事件
*/
function throttle(method, mustRunDelay) {
let timer,
args = arguments,
start;
return function loop() {
let self = this;
let now = Date.now();
if(!start){
start = now;
}
if(timer){
clearTimeout(timer);
}
if(now - start >= mustRunDelay){
method.apply(self, args);
start = now;
}else {
timer = setTimeout(function () {
loop.apply(self, args);
}, 50);
}
}
}
window.onscroll = throttle(function () {
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
},800)
vue输入节流,避免实时请求接口
在做搜索的时候,当搜索页面只有一个输入框、没有确定按钮的时候,只能在用户输入时请求服务端,查询数据。这样会导致频繁的发送请求,造成服务端压力。解决这个问题,可以使用vue做输入节流。
1.创建一个工具类,debounce.js
/***
* @param func 输入完成的回调函数
* @param delay 延迟时间
*/
export function debounce(func, delay){
let timer
return (...args)=>{
if(timer){
clearTimeout(timer)
}
timer=setTimeout(()=>{
func.apply(this, args)
},delay)
}
}
2、在搜索页面使用
<template>
<div class="xn-container">
<input type="text" class="text-input" v-model="search">
</div>
</template>
<script>
import {debounce} from '../utils/debounce'
export default {
name: 'HelloWorld',
data () {
return {
search: ''
}
},
created() {
this.$watch('search', debounce((newQuery) => {
// newQuery为输入的值
console.log(newQuery)
}, 200))
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.text-input {
display: block;
width: 100%;
height: 44px;
border: 1px solid #d5d8df;
}
</style>