道招

vue里面使用debounce,throttle注意点

如果您发现本文排版有问题,可以先点击下面的链接切换至老版进行查看!!!

vue里面使用debounce,throttle注意点

我们有时在自己的vue项目中不可避免的要监听类似scroll事件的,这是如果相对性能影响少点,只能会想到debounce防抖之类的。但是我们要注意了,addEventListener和removeEventListener必须要是同一个函数才行哦,不然removeEventListener是无法移除事件的,这样就容易造成内存泄露了。

平时我们的debounce一般这么用

methods: {
    createDebounce(ms, fn) {
      let prevTime;
      return () => {
        if (prevTime) {
          if (Date.now() - prevTime >= ms) {
            fn();
            prevTime = null;
          }
        } else {
          prevTime = Date.now();
        }
      };
    },
    scrollFn() {
        // ...处理逻辑
    }
}

那我们怎么配合addEventListener和removeEventListener使用呢? 比如

mounted() {
    window.document.addEventListener('scroll', this.createDebounce(800, this.scrollFn);
},
beforeDestroy() {
    window.document.removeEventListener('scroll', this.createDebounce(800, this.scrollFn);
},

首先这样用能起到防抖的作用的,但是removeEventListener是没什么作用的。 因为this.createDebounce执行后会返还一个匿名函数,removeEventListener想要取消的根本不是addEventListener中return的那个。 我们要利用闭包记录prevTime必然createDebounce需要返回一个函数。

怎么解决呢? 我们可以这样

data() {
    return {
        prevTime: null,
    };
},
mounted() {
    window.document.addEventListener('scroll', this.createDebounce(800, this.scrollFn);
},
beforeDestroy() {
    window.document.removeEventListener('scroll', this.createDebounce(800, this.scrollFn);
},
methods: {
    createDebounce(ms, fn) {
        if (this.prevTime) {
          if (Date.now() - this.prevTime >= ms) {
            fn();
            this.prevTime = null;
          }
        } else {
          this.prevTime = Date.now();
        }
    },
    scrollFn() {
        // ...处理逻辑
    }
}

不使用闭包了,直接用this.prevTime,搞定!

没想到好的方案前,这不失为一个解决方案。但是,你是不是觉得这个写法有点low了。

其实我们可以优雅点,这样写的。

created() {
    this.scroll = this.createDebounce(800, this.scrollFn);
},
mounted() {
    window.document.addEventListener('scroll', this.scroll);
},
beforeDestroy() {
    window.document.removeEventListener('scroll', this.scroll);
},
methods: {
    createDebounce(ms, fn) {
        if (this.prevTime) {
          if (Date.now() - this.prevTime >= ms) {
            fn();
            this.prevTime = null;
          }
        } else {
          this.prevTime = Date.now();
        }
    },
    scrollFn() {
        // ...处理逻辑
    }
}

我们可以直接在created里面在this上面加个方法,而不使用methods里面的方法。

created里面是有this的,可以增加属性或者方法的,并且即使template里面需要用到这个属性或者方法,也是能拿到的,但是要注意响应式的问题,这样直接创建的肯定不是响应式的。

更新时间:
上一篇:element-ui表单源码解析之el-input下一篇:用webpack的require.context优化vue store和router文件

相关文章

关注道招网公众帐号
道招开发者二群