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


Posted in Vue.js onDecember 02, 2020

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

节流函数

浏览器的一些事件,如: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 组件

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 组件节流函数的资料请关注三水点靠木其它相关文章!

Vue.js 相关文章推荐
vue element-ul实现展开和收起功能的实例代码
Nov 25 Vue.js
实用的 vue tags 创建缓存导航的过程实现
Dec 03 Vue.js
Vue+element-ui添加自定义右键菜单的方法示例
Dec 08 Vue.js
vue使用element-ui实现表单验证
Dec 13 Vue.js
浅析vue中的nextTick
Dec 28 Vue.js
Vue 修改网站图标的方法
Dec 31 Vue.js
vue组件是如何解析及渲染的?
Jan 13 Vue.js
vue实现倒计时功能
Mar 24 Vue.js
Vue和Flask通信的实现
May 19 Vue.js
Vue中插槽slot的使用方法与应用场景详析
Jun 08 Vue.js
vue封装数字翻牌器
Apr 20 Vue.js
vue 自定义组件添加原生事件
Apr 21 Vue.js
Vue3+elementui plus创建项目的方法
Dec 01 #Vue.js
Vue.js桌面端自定义滚动条组件之美化滚动条VScroll
Dec 01 #Vue.js
vue开发chrome插件,实现获取界面数据和保存到数据库功能
Dec 01 #Vue.js
vue实现表格合并功能
Dec 01 #Vue.js
vue element实现表格合并行数据
Nov 30 #Vue.js
Vue Elenent实现表格相同数据列合并
Nov 30 #Vue.js
vue中defineProperty和Proxy的区别详解
Nov 30 #Vue.js
You might like
PHP的伪随机数与真随机数详解
2015/05/27 PHP
PHP进阶学习之依赖注入与Ioc容器详解
2019/06/19 PHP
PHP全局使用Laravel辅助函数dd
2019/12/26 PHP
jQuery live
2009/05/15 Javascript
面向对象继承实例(a如何继承b问题)(自写)
2013/07/01 Javascript
获取非最后一列td值并将title设为该值的方法
2013/10/30 Javascript
jquery实现图片滚动效果的简单实例
2013/11/23 Javascript
JavaScript中几种排序算法的简单实现
2015/07/29 Javascript
JavaScript知识点总结(六)之JavaScript判断变量数据类型
2016/05/31 Javascript
AngularJS 过滤器的简单实例
2016/07/27 Javascript
JavaScript中英文字符长度统计方法示例【按照中文占2个字符】
2017/01/17 Javascript
Require.JS中的几种define定义方式示例
2017/06/01 Javascript
详解微信小程序 template添加绑定事件
2017/06/23 Javascript
Vue实现带进度条的文件拖动上传功能
2018/02/23 Javascript
js实现时分秒倒计时
2019/12/03 Javascript
vue接口请求加密实例
2020/08/11 Javascript
[02:07]2018DOTA2亚洲邀请赛主赛事第三日五佳镜头 fy极限反杀
2018/04/06 DOTA
详解Python之数据序列化(json、pickle、shelve)
2017/03/30 Python
对python:print打印时加u的含义详解
2018/12/15 Python
Python简直是万能的,这5大主要用途你一定要知道!(推荐)
2019/04/03 Python
Python面向对象总结及类与正则表达式详解
2019/04/18 Python
python格式化输出保留2位小数的实现方法
2019/07/02 Python
Python 中pandas索引切片读取数据缺失数据处理问题
2019/10/09 Python
python创建子类的方法分析
2019/11/28 Python
python绘制封闭多边形教程
2020/02/18 Python
浅谈python多线程和多线程变量共享问题介绍
2020/04/17 Python
Pycharm连接远程服务器过程图解
2020/04/30 Python
解决Django Haystack全文检索为空的问题
2020/05/19 Python
AmazeUI中各种的导航式菜单与解决方法
2020/08/19 HTML / CSS
JOSEPH官网:英国奢侈时尚品牌
2018/01/31 全球购物
工作时间上网检讨书
2014/02/03 职场文书
九一八事变演讲稿
2014/09/05 职场文书
2014年招生工作总结
2014/11/26 职场文书
经典搞笑版检讨书
2015/02/19 职场文书
创业计划书之养殖业
2019/10/11 职场文书
MySQL 语句执行顺序举例解析
2022/06/05 MySQL