gpt4 book ai didi

vue组件中节流函数的失效的原因和解决方法

转载 作者:qq735679552 更新时间:2022-09-27 22:32:09 24 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章vue组件中节流函数的失效的原因和解决方法由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

今天使用节流函数的时候遇见了一个问题,搞了半天才找到原因,所以在这里做个总结.

节流函数 。

浏览器的一些事件,如:resize,scroll,mousemove等。这些事件触发频率太过频繁,绑定在这些事件上的回调函数会不停的被调用,加重浏览器的负担,导致用户体验非常糟糕。所以先贤们发明了节流函数,简单版本如下:

?
1
2
3
4
5
6
7
8
9
10
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 ,而重绘时要使用节流函数防止性能损耗。正常情况下代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
< 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 循环加载了很多次:

?
1
2
3
4
5
< 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 组件

vue 组件在代码编译的阶段,组件 svgMark 中的方法 reDraw: throttle(function() { this.index++ }, 500) 就已经被编译成了类似如下函数:

?
1
2
3
4
5
6
7
reDraw: ƒ (...args) {
  let now = Date.now()
  if (now - last > wait) {
  last = now
  f.apply( this , args)
  }
}

由于函数是引用类型,所有使用子组件 svgMark 的 methods 中的 reDraw 都指向了同一个内存地址,也就是说所有子组件的 reDraw 方法都是同一个函数.

因为所有组件都公用了同一个节流函数,当然就会产生节流了。那怎么解决问题呢?对症下药就要让每个组件产生自己的节流函数,而不产生共用。代码如下 。

子组件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
< 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 组件节流函数的资料请关注我其它相关文章! 。

原文链接:https://juejin.cn/post/6901231253102526477?utm_source=tuicool&utm_medium=referral 。

最后此篇关于vue组件中节流函数的失效的原因和解决方法的文章就讲到这里了,如果你想了解更多关于vue组件中节流函数的失效的原因和解决方法的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com