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 相关文章推荐
JS获取并操作iframe中元素的方法
Mar 21 Javascript
Extjs改变树节点的勾选状态点击按钮将复选框去掉
Nov 14 Javascript
js对table的td进行相同内容合并示例详解
Dec 27 Javascript
jquery 鼠标滑动显示详情应用示例
Jan 24 Javascript
jQuery事件的绑定、触发、及监听方法简单说明
May 10 Javascript
JS表单数据验证的正则表达式(常用)
Feb 18 Javascript
js实现每日签到功能
Nov 29 Javascript
React如何实现浏览器打印部分内容详析
May 19 Javascript
Vue.js实现tab切换效果
Jul 24 Javascript
vue2.0项目集成Cesium的实现方法
Jul 30 Javascript
通过layer实现可输入的模态框的例子
Sep 27 Javascript
vue.config.js常用配置详解
Nov 14 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
收集的php编写大型网站问题集
2007/03/06 PHP
ThinkPHP3.1之D方法实例详解
2014/06/20 PHP
PHP抽奖算法程序代码分享
2015/10/08 PHP
php实现的mongoDB单例模式操作类
2018/01/20 PHP
Javascript技巧之不要用for in语句对数组进行遍历
2010/10/20 Javascript
js TextArea的选中区域处理
2010/12/28 Javascript
jqTransform form表单美化插件使用方法
2012/07/05 Javascript
JS获取url链接字符串 location.href
2013/12/23 Javascript
jQuery中Ajax的load方法详解
2015/01/14 Javascript
jQuery学习笔记之jQuery中的$
2015/01/19 Javascript
PHP实现的各种中文编码转换类分享
2015/01/23 Javascript
javascript中cookie对象用法实例分析
2015/01/30 Javascript
jQuery的事件委托实例分析
2015/07/15 Javascript
javascript简单实现滑动菜单效果的方法
2015/07/27 Javascript
基于RequireJS和JQuery的模块化编程——常见问题全面解析
2016/04/14 Javascript
详解vue组件通信的三种方式
2017/06/30 Javascript
Vue0.1的过滤代码如何添加到Vue2.0直接使用
2017/08/23 Javascript
vue-cli3 项目优化之通过 node 自动生成组件模板 generate View、Component
2019/04/30 Javascript
详解jenkins自动化部署vue
2019/05/14 Javascript
对layui初始化列表的CheckBox属性详解
2019/09/13 Javascript
JS创建自定义对象的六种方法总结
2020/12/15 Javascript
Python AES加密模块用法分析
2017/05/22 Python
Python网络爬虫与信息提取(实例讲解)
2017/08/29 Python
Flask框架Jinjia模板常用语法总结
2018/07/19 Python
浅谈pycharm下找不到sqlalchemy的问题
2018/12/03 Python
python实现beta分布概率密度函数的方法
2019/07/08 Python
Python Pickle 实现在同一个文件中序列化多个对象
2019/12/30 Python
Pyqt5 关于流式布局和滚动条的综合使用示例代码
2020/03/24 Python
使用python从三个角度解决josephus问题的方法
2020/03/27 Python
台湾最大网路书店:博客来
2018/03/18 全球购物
Kickers鞋英国官网:男士、女士和儿童鞋
2021/03/08 全球购物
入职担保书怎么写
2014/05/12 职场文书
电信营业员岗位职责
2015/04/14 职场文书
浅析InnoDB索引结构
2021/04/05 MySQL
windows下快速安装nginx并配置开机自启动的方法
2021/05/11 Servers
浅谈如何保证Mysql主从一致
2022/03/13 MySQL