vue中节流函数失效是什么情况?如何解决?
Admin 2021-10-13 群英技术资讯 1263 次浏览
这篇文章主要介绍vue中节流函数的相关内容,一些朋友有遇到节流函数失效的问题,那么这究竟是怎么回事呢?我们该怎样解决这个问题?对此下面小编给大家总结了一下原因。
节流函数
浏览器的一些事件,如:resize,scroll,mousemove等。这些事件触发频率太过频繁,绑定在这些事件上的回调函数会不停的被调用,加重浏览器的负担,导致用户体验非常糟糕。所以先贤们发明了节流函数,简单版本如下:
function throttle (f, wait = 200) {
let last = 0
return function (...args) {
let now = Date.now()
if (now - last > wait) {
last = now
f.apply(this, args)
}
}
}
假设有一个 vue 组件 svgMark。这个组件中渲染的元素要在页面窗口大小发生变化时重绘 reDraw ,而重绘时要使用节流函数防止性能损耗。正常情况下代码如下:
<template>
<div>{{ index }}</div>
</template>
<script>
import { throttle } from 'lodash'
export default {
name: 'SvgMark',
data() {
return {
index: 0
}
},
mounted() {
window.addEventListener('resize', this.reDraw)
},
beforeDestroy() {
window.removeEventListener('resize', this.reDraw)
},
methods: {
reDraw: throttle(function() {
this.index++
}, 500)
}
}
</script>
</script>
一般情况下这样用没什么问题。但是有这样一个场景,使用节流函数时却失效了,即当这个组件被 v-for 循环加载了很多次:
<template> <div> <svgMark v-for="item in 10" :key="item.id" /> </div> </template>
这个时候无论渲染了多少个 svgMark 组件,在窗口大小改变的时候却只触发了第一个组件和第 n 割组件的重绘,为什么其他组件没有触发呢?这就要从头说起了。
节流函数在初始化的时候产生了一个闭包,闭包内保存了变量 last ,这个 last 记录了上一次执行 f 函数的时间。而当下一次触发节流函数的时候,如果此时时间 now 减去上次时间 last 小于了我们规定的节流时间 wait ,那么函数 f 将不会执行。
很显然,第一个子组件在触发节流函数的时候产生了一个 last,而第二个组件在触发节流函数时候的时产生的 now 并没有满足 now - last > wait 的条件,所以没有执行重绘代码。而到了第 n 个组件触发节流函数的时候,满足了 now - last > wait 的条件所以重绘成功了。
vue 组件在代码编译的阶段,组件 svgMark 中的方法 reDraw: throttle(function() { this.index++ }, 500) 就已经被编译成了类似如下函数:
reDraw: ƒ (...args) {
let now = Date.now()
if (now - last > wait) {
last = now
f.apply(this, args)
}
}
由于函数是引用类型,所有使用子组件 svgMark 的 methods 中的 reDraw 都指向了同一个内存地址,也就是说所有子组件的 reDraw 方法都是同一个函数。
因为所有组件都公用了同一个节流函数,当然就会产生节流了。那怎么解决问题呢?对症下药就要让每个组件产生自己的节流函数,而不产生共用。代码如下
子组件:
<template>
<div>{{ index }}</div>
</template>
<script>
import { throttle } from 'lodash'
export default {
name: 'SvgMark',
data() {
return {
index: 0
}
},
mounted() {
this.reDraw = throttle(() => {
this.index++
}, 500)
window.addEventListener('resize', this.reDraw)
},
beforeDestroy() {
window.removeEventListener('resize', this.reDraw)
}
}
</script>
我们在 mounted 声明周期函数中手动声明了 reDraw 函数替代 methods 中的 reDraw ,这样在每个组件初始化的时候都会产生一个自己的节流函数了。需要注意此时节流函数的参数使用了箭头函数,因为这样 this 才会指向组件实例。
以上就是关于vue节流函数失效的原因及方法的介绍啦,上述示例具有一定的借鉴价值,有需要的朋友可以参考学习,希望对大家学习vue组件有帮助,想要了解更多大家可以继续浏览群英网络其他相关的文章。
文本转载自脚本之家
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
今天我们来了解一下vuex,下文会给大家分享vuex中四大对象state、mutations、getters、actions以及他们的用法,对新手学习和理解vuex对象有一定的帮助,感兴趣的朋友就继续往下看吧。
目录data里面的数据相互使用具体代码如下data里的数据不能相互引用问题data里面的数据相互使用今天在写代码的时候,遇到一个问题,我想使用data里面的一个对象使用data里面的某个数据,附图片:我想让active的值给params对象里面的topicListType使用,我不想直接在一个方法里面改变这个值(想改的
react怎样捕获异常?对新手来说,常常可能会出现代码出错的情况,但其实出错并不可怕,关键是怎么处理。一下朋友对于react的应用的错误捕捉可能不是很了解,对此,这篇文章就给大家介绍一下,对帮助大家除了代码错误有一定的帮助,需要的朋友可以参考。
本篇文章给大家带来了关于JavaScript的相关知识,其中主要整理了日期对象Date的相关问题,包括了Date对象的创建、Date对象的方法等等内容,下面一起来看一下,希望对大家有帮助。
jQuery中获取表格行数的思路和方法是什么?首先我们需要知道tr标签,tr标签用于定义HTML表格中的一行,因此我们要获取表格行数的思路就是坚持这个表格有多少个tr标签就可以了,那么具体怎样实现呢?我们接着往下看吧。
成为群英会员,开启智能安全云计算之旅
立即注册关注或联系群英网络
7x24小时售前:400-678-4567
7x24小时售后:0668-2555666
24小时QQ客服
群英微信公众号
CNNIC域名投诉举报处理平台
服务电话:010-58813000
服务邮箱:service@cnnic.cn
投诉与建议:0668-2555555
Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 ICP核准(ICP备案)粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008