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 相关文章推荐
基于jquery插件实现常见的幻灯片效果
Nov 01 Javascript
JavaScript数组随机排列实现随机洗牌功能
Mar 19 Javascript
深入理解JS正则表达式---分组
Jul 18 Javascript
BOM系列第一篇之定时器setTimeout和setInterval
Aug 17 Javascript
codeMirror插件使用讲解
Jan 16 Javascript
js for循环倒序输出数组元素的实例
Mar 01 Javascript
JS实现页面打印(整体、局部)
Aug 18 Javascript
初识 Vue.js 中的 *.Vue文件
Nov 22 Javascript
Vue开发实现吸顶效果的示例代码
Aug 21 Javascript
监听element-ui table滚动事件的方法
Mar 26 Javascript
微信小程序用户拒绝授权的处理方法详解
Sep 20 Javascript
el-table表头根据内容自适应完美解决表头错位和固定列错位
Jan 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
Thinkphp5框架简单实现钩子(Hook)行为的方法示例
2019/09/03 PHP
js异或加解密效果代码
2008/06/25 Javascript
javasctipt如何显示几分钟前、几天前等
2014/04/30 Javascript
js 采用delete实现继承示例代码
2014/05/20 Javascript
jQuery设置和移除文本框默认值的方法
2015/03/09 Javascript
Angularjs中的页面访问权限怎么设置
2016/11/11 Javascript
JS中关于事件处理函数名后面是否带括号的问题
2016/11/16 Javascript
简单实现js浮动框
2016/12/13 Javascript
详解Angular2表单-模板驱动的表单(Template-Driven Forms)
2017/08/04 Javascript
react中实现搜索结果中关键词高亮显示
2018/07/31 Javascript
微信小程序实现banner图轮播效果
2020/06/28 Javascript
浅谈Vue.set实际上是什么
2019/10/17 Javascript
vue实现拖拽效果
2019/12/23 Javascript
详解如何在vue+element-ui的项目中封装dialog组件
2020/12/11 Vue.js
python3.0 字典key排序
2008/12/24 Python
python3 自动识别usb连接状态,即对usb重连的判断方法
2019/07/03 Python
Python对接支付宝支付自实现功能
2019/10/10 Python
python类中super() 的使用解析
2019/12/19 Python
pytorch三层全连接层实现手写字母识别方式
2020/01/14 Python
深入浅析Python 命令行模块 Click
2020/03/11 Python
Python中random模块常用方法的使用教程
2020/10/04 Python
python切片作为占位符使用实例讲解
2021/02/17 Python
html5使用canvas画一条线
2014/12/15 HTML / CSS
Madewell美德威尔美国官网:美国休闲服饰品牌
2016/11/25 全球购物
Lentiamo丹麦:购买便宜的隐形眼镜
2021/01/13 全球购物
是什么让J2EE适合用来开发多层的分布式的应用
2015/01/16 面试题
Linux上比较文件的命令都有哪些
2012/02/24 面试题
销售员自我评价怎么写
2013/09/19 职场文书
校三好学生主要事迹
2014/01/11 职场文书
小小的船教学反思
2014/02/21 职场文书
党员干部一句话承诺
2014/05/30 职场文书
高中学校对照检查材料
2014/08/31 职场文书
2015新员工试用期工作总结
2014/12/12 职场文书
村官个人总结范文
2015/03/03 职场文书
超市啤酒狂欢夜策划方案范文!
2019/07/03 职场文书
Python实现视频中添加音频工具详解
2021/12/06 Python