vue组件中节流函数的失效的原因和解决方法
今天使用节流函数的时候遇见了一个问题,搞了半天才找到原因,所以在这里做个总结。
节流函数
浏览器的一些事件,如:resize,scroll,mousemove等。这些事件触发频率太过频繁,绑定在这些事件上的回调函数会不停的被调用,加重浏览器的负担,导致用户体验非常糟糕。所以先贤们发明了节流函数,简单版本如下:
functionthrottle(f,wait=200){ letlast=0 returnfunction(...args){ letnow=Date.now() if(now-last>wait){ last=now f.apply(this,args) } } }
假设有一个vue组件svgMark。这个组件中渲染的元素要在页面窗口大小发生变化时重绘reDraw,而重绘时要使用节流函数防止性能损耗。正常情况下代码如下:
{{index}}
一般情况下这样用没什么问题。但是有这样一个场景,使用节流函数时却失效了,即当这个组件被v-for循环加载了很多次:
这个时候无论渲染了多少个svgMark组件,在窗口大小改变的时候却只触发了第一个组件和第n割组件的重绘,为什么其他组件没有触发呢?这就要从头说起了。
- 节流函数
节流函数在初始化的时候产生了一个闭包,闭包内保存了变量last,这个last记录了上一次执行f函数的时间。而当下一次触发节流函数的时候,如果此时时间now减去上次时间last小于了我们规定的节流时间wait,那么函数f将不会执行。
很显然,第一个子组件在触发节流函数的时候产生了一个last,而第二个组件在触发节流函数时候的时产生的now并没有满足now-last>wait的条件,所以没有执行重绘代码。而到了第n个组件触发节流函数的时候,满足了now-last>wait的条件所以重绘成功了。
- vue组件
vue组件在代码编译的阶段,组件svgMark中的方法reDraw:throttle(function(){this.index++},500)就已经被编译成了类似如下函数:
reDraw:ƒ(...args){ letnow=Date.now() if(now-last>wait){ last=now f.apply(this,args) } }
由于函数是引用类型,所有使用子组件svgMark的methods中的reDraw都指向了同一个内存地址,也就是说所有子组件的reDraw方法都是同一个函数。
因为所有组件都公用了同一个节流函数,当然就会产生节流了。那怎么解决问题呢?对症下药就要让每个组件产生自己的节流函数,而不产生共用。代码如下
子组件:
{{index}}
我们在mounted声明周期函数中手动声明了reDraw函数替代methods中的reDraw,这样在每个组件初始化的时候都会产生一个自己的节流函数了。需要注意此时节流函数的参数使用了箭头函数,因为这样this才会指向组件实例。
以上就是节流函数带给我的坑,现在分享给大家。[下班][鼓掌]
以上就是vue组件中节流函数的失效和解决方法的详细内容,更多关于vue组件节流函数的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。