现实中使用场景也挺多,比如搜索框,滚动条,及时保存…使用防抖和节流可以优化性能
防抖(debounce)
首先以搜索框为例:
为了防止接口频繁调用,如果在规定时间内没有再次触发事件,就执行函数;如果规定时间内再次触发,那么当前计时取消,重新开始计时。
效果:如果短时间内大量触发同一个事件,只会执行一次函数
<template>
<div class="about">
<el-autocomplete v-model="state" :fetch-suggestions="querySearchAsync" placeholder="请输入内容" style="width:100%">
<template #default="scope">
<el-table :data="contents">
<el-table-column prop="name" label="作者" width="100">
</el-table-column>
<el-table-column prop="value" label="古诗">
</el-table-column>
</el-table>
</template>
</el-autocomplete>
</div>
</template>
<script>
import ancient from "../uilt/index";
import { debounce } from "../uilt/debounce";
// import { throttle } from "../uilt/throttle";
export default {
data() {
return {
state: "",
contents: [],
ancient: ancient,
};
},
methods: {
querySearchAsync(name, callback) {
debounce(this.querySearch(name, callback), 1000);
},
querySearch(name, callback) {
let arr = [];
if (name != "" && name.length > 0) {
//获取搜索数据
arr = this.ancient.filter((item) => {
if (item.name.includes(name)) {
return item;
}
});
}
if (arr.length > 0) {
this.contents = arr;
// 调用 callback 返回建议列表的数据,是一个数组类型
//防止循环多次,截取数组的第一条
let arrs = this.contents.slice(0, 1);
callback(arrs);
} else {
callback(["暂无数据"]);
}
},
},
};
</script>
debounce .js
function debounce(fn, delay) {
let timer = null;
return function () {
if (timer) {
//如果timer有值的话代码已经执行过了。执行了的话是不是要清空
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(null, arguments);
}, delay); //如果没有的话代表还未在规定的时间内执行
};
}
export { debounce };
对于短时间内连续触发的事件,防抖的含义就是让某个时间期限(如上面的1000毫秒)内,事件处理函数只执行一次。
节流(throttle)
如果在限定时间段内,不断触发滚动事件(比如某个用户闲着无聊,按住滚动不断的拖来拖去),只要不停止触发,理论上就永远不会输出当前距离顶部的距离。
效果:如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效。
<template>
<div>
<div class="home">12</div>
</div>
</template>
<script>
import { throttle } from "../uilt/throttle";
function showTop() {
var scrollTop =
document.body.scrollTop || document.documentElement.scrollTop;
console.log("滚动条位置:" + scrollTop);
}
window.onscroll = throttle(showTop, 1000);
export default {};
</script>
<style scoped>
.home {
height: 1000px;
width: 100px;
border: 1px solid #000;
}
</style>
throttle.js
export function throttle(fn, delay) {
//节流
let canRun = true; // 通过闭包保存一个标记
return function () {
if (!canRun) return; // 在函数开头判断标记是否为true,不为true则return
canRun = false; // 立即设置为false
setTimeout(() => {
// 将外部传入的函数的执行放在setTimeout中
fn.call(this);
// 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。当定时器没有执行的时候标记永远是false,在开头被return掉
canRun = true;
}, delay);
};
}
如果一直拖着滚动条进行滚动,那么会以1s的时间间隔,持续输出当前位置和顶部的距离
也可以将方法写在main.js中
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import ElementUI from 'element-ui';
import './assets/element-variables.scss';
Vue.use(ElementUI);
Vue.config.productionTip = false;
Vue.prototype.debounce = function (fn, delay) {
//防抖
let timer = null; //声明一个timer
return function () {
if (timer) {
//如果timer有值的话代码已经执行过了。执行了的话是不是要清空
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(null, arguments);
}, delay); //如果没有的话代表还未在规定的时间内执行
};
};
new Vue({
router,
store,
render: (h) => h(App),
}).$mount('#app');
富文本每隔30秒保存一次
https://blog.csdn.net/Jenny_ljj/article/details/120888977