vue 实现setInterval 创建和销毁实例


Posted in Javascript onJuly 21, 2020

问题

setInterval 是间隔调用,与之类似的还有 setTimeout。这两个 API 通常用来做 ajax 短连接轮询数据。

比如有一个 logs.vue 是用来展示某个正在执行的进程产生的日志:

<template>
 <div>
 <p v-for="item in logList" :key="item.time">
  <span>{{"[" + item.time + "]"}}</span>
  <span>{{ item.log }}</span>
 </p>
 </div>
</template>
<script>
 import { Component, Vue, Watch, Prop, Emit } from 'vue-property-decorator'
 import { getLogList } from './api'
 @Component({})
 export default class extends Vue {
 logList = []
 timer = null
 mounted(){
  this.getData()
 }
 async getData(){
  let r = await getLogList()
  if(r && r.logList){
  this.logList = r.logList
  }
  this.timer = setTimeout(()=>{
  console.log(this.timer);
  this.getData()
  }, 1000)
 }
 beforeDestory(){
  clearTimeout(this.timer)
  this.timer = null;
 }
 }
</script>

这段代码看上去没啥问题,但是测试的时候你会发现,有时候路由已经跳转了,获取进程日志的接口依然在不断调用,甚至,有时候接口调用速度非常快,一秒可能有好几个请求。

分析

beforeDestory 是组件销毁前的生命周期的钩子,这个钩子函数一定会调用,但是能不能彻底销毁 setTimeout 呢?答案是不能。

打开控制台就能看到不断打印出来的 id

vue 实现setInterval 创建和销毁实例

这是因为,每次使用 clearTimeout 清除掉的是上一次的 id, 而不是本次正要执行的,这种情况,对于使用 setInterval 也是一样的。

根本原因在于,每次调用 getData, this.timer 是在不断的被赋予新的值,而不是一成不变的。

在以前的原生 js 中,我们通常这样写:

var timer = null
function init(){
 timer = setInterval(function(){
 getData()
 })
}
function getData(){}
window.onload = init
window.onunload = function(){
 clearInterval(timer)
}

由于上面的 timer 始终保持一个值,所以这里的清除是有效的

解决

vue 提供了 程序化的事件侦听器 来处理这类边界情况

按照文档的说法,我们的代码可以这样来更改

<script>
 import { Component, Vue, Watch, Prop, Emit } from 'vue-property-decorator'
 import { getLogList } from './api'
 @Component({})
 export default class extends Vue {
 logList = []
 // timer = null
 mounted(){
  this.getData()
 }
 async getData(){
  let r = await getLogList()
  if(r && r.logList){
  this.logList = r.logList
  }
  const timer = setTimeout(()=>{
  this.getData()
  }, 1000)
  this.$once('hook:beforeDestroy', function () {
    clearTimeout(timer)
  })
 }
 }
</script>

这样写,还解决了两个潜在问题

在组件实例中保存这个 timer,最好只有生命周期钩子有访问它的权限。但是实例中的 timer 会视为杂物

如果建立代码独立于清理代码,会使得我们比较难于程序化地清理所建立的东西

如果你是在项目中引入了 ts,那么可能会导致在组件销毁的时候,定时器不能成功清除,这时候,你需要使用

const timer = window.setTimeout(()=>{
 this.getData()
}, 1000)
this.$once('hook:beforeDestroy', function () {
  window.clearTimeout(timer)
})

如果你漏掉了其中一个 window,那么很可能会遇上类似的 ts 报错:Type 'Timer' is not assignable to type 'number',这是因为 node typings

It seems like you are using node typings which override setInterval() as something that returns NodeJS.Timer. If you're running in the browser, it doesn't make a whole lot of sense to use these,

结论

我们可以通过 程序化的事件侦听器 来监听销毁我们创建的任何代码示例

除了 setTimeout 和 setInterval ,通常还有一些第三方库的对象示例,如 timePicker,datePicker,echarts图表等。

mounted: function () {
 // Pikaday 是一个第三方日期选择器的库
  var picker = new Pikaday({
   field: this.$refs.input,
   format: 'YYYY-MM-DD'
  })
 // 在组件被销毁之前,也销毁这个日期选择器。
  this.$once('hook:beforeDestroy', function () {
   picker.destroy()
  })
}

以上这篇vue 实现setInterval 创建和销毁实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
发布一个高效的JavaScript分析、压缩工具 JavaScript Analyser
Nov 30 Javascript
仿新浪微博登陆邮箱提示效果的js代码
Aug 02 Javascript
js 获取时间间隔实现代码
May 12 Javascript
AspNet中使用JQuery上传插件Uploadify详解
May 20 Javascript
javascript实现dom元素可拖动
Mar 21 Javascript
jQuery包裹节点用法完整示例
Sep 13 Javascript
关于AngularJs数据的本地存储详解
Jan 20 Javascript
微信小程序之圆形进度条实现思路
Feb 22 Javascript
利用JS实现一个同Excel表现的智能填充算法
Aug 13 Javascript
Vue源码解读之Component组件注册的实现
Aug 24 Javascript
vue 实现特定条件下绑定事件
Nov 09 Javascript
js面向对象编程OOP及函数式编程FP区别
Jul 07 Javascript
解决vue.js中settimeout遇到的问题(时间参数短效果不稳定)
Jul 21 #Javascript
Vue清除定时器setInterval优化方案分享
Jul 21 #Javascript
解决vue 使用setTimeout,离开当前路由setTimeout未销毁的问题
Jul 21 #Javascript
JavaScript undefined及null区别实例解析
Jul 21 #Javascript
Vue 解决父组件跳转子路由后当前导航active样式消失问题
Jul 21 #Javascript
Vue切换组件实现返回后不重置数据,保留历史设置操作
Jul 21 #Javascript
vue 实现tab切换保持数据状态
Jul 21 #Javascript
You might like
ThinkPHP CURD方法之data方法详解
2014/06/18 PHP
Yii2针对游客、用户防范规则和限制的解决方法分析
2016/10/08 PHP
laravel框架中表单请求类型和CSRF防护实例分析
2019/11/23 PHP
jQuery 处理网页内容的实现代码
2010/02/15 Javascript
jQuery实现鼠标滑过遮罩并高亮显示效果
2013/07/16 Javascript
JQuery与JS里submit()的区别示例介绍
2014/02/17 Javascript
jQuery 写的简单打字游戏可以提示正确和错误的次数
2014/07/01 Javascript
JS对象与json字符串格式转换实例
2014/10/28 Javascript
javascript阻止事件冒泡和浏览器的默认行为
2017/01/21 Javascript
JavaScript实现快速排序的方法分析
2018/01/10 Javascript
Vue的路由动态重定向和导航守卫实例
2018/03/17 Javascript
解决vue 单文件组件中样式加载问题
2019/04/24 Javascript
策略模式实现 Vue 动态表单验证的方法
2019/09/16 Javascript
Vuex modules模式下mapState/mapMutations的操作实例
2019/10/17 Javascript
vue项目配置同一局域网可使用ip访问的操作
2020/10/23 Javascript
JQuery绑定事件四种实现方法解析
2020/12/02 jQuery
[57:38]2018DOTA2亚洲邀请赛3月30日 小组赛A组 OpTic VS OG
2018/03/31 DOTA
python抓取某汽车网数据解析html存入excel示例
2013/12/04 Python
Python def函数的定义、使用及参数传递实现代码
2014/08/10 Python
python学习之编写查询ip程序
2016/02/27 Python
Python创建对称矩阵的方法示例【基于numpy模块】
2017/10/12 Python
学习Python selenium自动化网页抓取器
2018/01/20 Python
python之pandas用法大全
2018/03/13 Python
Python3.6通过自带的urllib通过get或post方法请求url的实例
2018/05/10 Python
解析pip安装第三方库但PyCharm中却无法识别的问题及PyCharm安装第三方库的方法教程
2020/03/10 Python
银行实习生自我鉴定范文
2013/09/19 职场文书
机电一体化专业应届本科生求职信
2013/09/27 职场文书
自我评价范文分享
2014/01/04 职场文书
加拿大留学自荐信
2014/01/28 职场文书
数学系毕业生求职信
2014/05/29 职场文书
材料化学专业求职信
2014/07/15 职场文书
2014年国庆节演讲稿
2014/09/19 职场文书
个人借条范本
2015/05/25 职场文书
2015中学学校工作总结
2015/07/20 职场文书
解决Pytorch dataloader时报错每个tensor维度不一样的问题
2021/05/28 Python
win10电脑双屏显示一个黑屏怎么办?win10电脑双屏显示一个黑屏解决方法
2022/07/15 数码科技