大家好,欢迎来到IT知识分享网。
下面以3个方式实现防抖节流
通过vue的data实现防抖节流
利用vue的data属性可以被实例全局调用,并且不被销毁的特点实现防抖节流
<!DOCTYPE html>
<html lang="en">
<body>
<div id="app">
<h3>vue 通过data属性实现防抖节流</h3>
<input placeholder="输入以测试防抖" @input="onDebounce">
<input placeholder="输入以测试节流" @input="onThrottle">
</div>
</body>
</html>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
<script> new Vue({
el: '#app', methods: {
onDebounce() {
clearTimeout(this.debounceTimer) this.debounceTimer = setTimeout(() => {
console.log('防抖...') }, 500) }, onThrottle() {
if (this.throttleCanRun === undefined) {
this.throttleCanRun = true } if (!this.throttleCanRun) return this.throttleCanRun = false setTimeout(() => {
console.log('节流...') this.throttleCanRun = true }, 500) }, } }) </script>
虽然在vue中data里面的属性也可以达到闭包的效果(变量不被销毁),但是如果项目中需要将防抖节流抽离封装,data的属性就不能实现。
那么,有没有什么方案可以达到data变量不被销毁效果呢?这让我们想起闭包,闭包可以让变量私有化,并且变量不被销毁。
在使用闭包实现防抖节流之前,我们先看一个最初闭包实现
var closure = (function () {
// 函数A所在的作用域
var a = 0
return function () {
// 函数A
// 在这里调用a,即函数与函数所在的作用域发生引用捆绑
console.log(a++)
}
})()
/* 输入看到的是a不断累加,说明a不被销毁。 并没有重置(因为a是在立即执行函数执行时声明), 立即执行函数执行时创建一个闭包, */
closure() // 0
closure() // 1
closure() // 2
通过闭包实现防抖节流
利用闭包中变量不被销毁,私有性实现防抖节流
<!DOCTYPE html>
<html lang="en">
<body>
<div id="app">
<h3>vue 通过闭包实现防抖节流</h3>
<input placeholder="输入以测试防抖" @input="onDebounce">
<input placeholder="输入以测试节流" @input="onThrottle">
</div>
</body>
</html>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
<script> /* 闭包只能声明一次, 如果放在methods将会随事件触发而声明, 所以需将闭包提取出来, 通过立即执行函数创建闭包 */ const debounce = (() => {
// 利用闭包使变量debounceTimer私有化,不被销毁 let debounceTimer = null return function () {
clearTimeout(debounceTimer) debounceTimer = setTimeout(() => {
console.log('防抖...') }, 500) } })() const throttle = (() => {
// 利用闭包使变量throttleCanRun私有化,不被销毁 let throttleCanRun = true return function () {
if (!throttleCanRun) return throttleCanRun = false setTimeout(() => {
console.log('节流...') throttleCanRun = true }, 500) } })() new Vue({
el: '#app', methods: {
onDebounce() {
debounce() }, onThrottle() {
throttle() }, } }) </script>
闭包方式封装防抖节流
防抖节流优化封装,可在项目中抽离到为工具函数
<!DOCTYPE html>
<html lang="en">
<body>
<div id="app">
<h3>vue 闭包实现防抖节流封装</h3>
<p>tips: 请打开控制台观察打印变化</p>
<input placeholder="输入以测试防抖" @input="onDebounce">
<input placeholder="输入以测试节流" @input="onThrottle">
<input placeholder="输入以测试时间差节流" @input="onTimeThrottle">
</div>
</body>
</html>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
<script> const debounce = (() => {
let debounceTimer = null return function (fn, delay) {
clearTimeout(debounceTimer) debounceTimer = setTimeout(fn, delay) } })() // 计时器实现节流 const throttle = (() => {
// 创建闭包时声明throttleCanRun为true let throttleCanRun = true return function (fn, delay) {
// 只有第一次执行,或每隔delay毫秒,throttleCanRun才为true,才能往下执行 if (!throttleCanRun) return /* 每次执行到这里都将throttleCanRun置为false, 而throttleCanRun置为true需等到delay毫秒后才触发 达到每隔delay毫秒后,throttleCanRun变为true一次, 达到节流的目的 */ throttleCanRun = false setTimeout(() => {
fn() throttleCanRun = true }, delay) } })() // 时间差实现节流 const timeThrottle = (() => {
let start return function (fn, delay) {
// 第一次触发事件时,初始化start if (!start) {
/* 第一次触发事件时先执行fn, 因为这里不执行fn的话, 当用户触发事件维持时间少于delay毫秒时, fn将不被触发*/ fn() start = new Date() } // 当事件反复触发,这里判断时间差是否大于delay if (new Date() - start > delay) {
fn() // 重置start为最新时间 start = new Date() } } })() new Vue({
el: '#app', methods: {
onDebounce() {
// 调用时需注意this指向,可使用箭头函数,或者使用self = this debounce(() => {
console.log('防抖...') }, 500) }, onThrottle() {
throttle(() => {
console.log('节流...') }, 300) }, onTimeThrottle() {
timeThrottle(() => {
console.log('时间差节流...') }, 300) } } }) </script>
>>> github源码
>>> github page 在线演示
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/10702.html