Vue中使用防抖或节流及监听事件addEventListener时防抖或节流
1.首先,需要先写好一个防抖函数或节流函数
// 防抖函数 export function debounce(fn, delay){ let timeout = null return function(){ let args = arguments if(timeout) window.clearTimeout(timeout) timeout = setTimeout(() => { fn.apply(this, args) }, delay) } } // 节流函数 export function throttle(fn, delay){ let timeout = null return function(){ let args = arguments if(!timeout){ timeout = setTimeout(() => { timeout = null fn.apply(this, args) }, delay) } } }
然后,在vue文件中引用,并调用:
methods: { handleClick(){ this.debounce(this) }, debounce: debounce((vm) => { // do something,这里this不指向Vue实例,用vm传入 }, 1000), }
节流同理。
2.如果要在监听某个事件的时候使用,这时候大致差不多:
mounted(){ let self = this window.addEventListener('scroll',this.scroll.bind(this, self)) }, methods: { scroll: throttle((self) => { // 用bind就可以给箭头函数传参,不用bind则这里不能用箭头函数 var body = document.body // 获取滚动条的dom var scrollTop = body.scrollTop || window.pageYOffset var windowHeight = body.clientHeight var scrollHeight = body.scrollHeight if(scrollTop+windowHeight>=scrollHeight){ self.scrollBottom = true }else{ self.scrollBottom = false } },300) }
这里需要注意的是this的指向,一般来说当函数内使用箭头函数时此时函数内的this指向最近的函数this指向,即指向window,使用普通函数function时指向调用它的对象;
在addEventListener中有所不同,window.addEventListener('scroll') 中,一般来说箭头函数指向最近的this指向,是window,普通函数指向调用它的对象,也是window;
但是在Vue中不是这样,使用箭头函数时,指向undefined,而普通函数指向 Vue实例, 我想原因在于这里的scroll是一个匿名函数,在Vue中是处于严格模式的,所以指向undefined,而普通函数则处在Vue实例中,所以指向Vue实例;
所以如果要使用箭头函数,而且已知箭头函数的指向不能被bind、call、apply改变,而函数内需要使用Vue实例,那么就可以考虑为函数传参,在考虑这里只是需要传参,不能执行函数,所以只能用bind,就如上代码所示。
所以这里有两种写法,最后,别忘了在销毁组件前移除事件监听,否则会造成内存泄露。