vue 实现setInterval 创建和销毁实例

所属分类: 网络编程 / JavaScript 阅读数: 377
收藏 0 赞 0 分享

问题

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

这是因为,每次使用 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如何判断查询日期是否为有效日期,需要的朋友可以参考下
收藏 0 赞 0 分享

jquery实现的蓝色二级导航条效果代码

这篇文章主要介绍了jquery实现的蓝色二级导航条效果代码,涉及jquery鼠标事件及页面样式的动态切换效果实现技巧,非常简单实用,需要的朋友可以参考下
收藏 0 赞 0 分享

ajax如何实现页面局部跳转与结果返回

AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术,通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新,本篇文章给大家介绍ajax如何实现页面局部跳转与结果返
收藏 0 赞 0 分享

jQuery实现的类似淘宝网站搜索框样式代码分享

这篇文章主要介绍了类似淘宝网站搜索框样式实现代码,推荐给大家,有需要的小伙伴可以参考下。
收藏 0 赞 0 分享

js实现的黑背景灰色二级导航菜单效果代码

这篇文章主要介绍了js实现的黑背景灰色二级导航菜单效果代码,涉及javascript操作页面元素动态切换的实现技巧,非常具有实用价值,需要的朋友可以参考下
收藏 0 赞 0 分享

jQuery仿360导航页图标拖动排序效果代码分享

这篇文章主要为大家详细介绍了360导航页图标拖动排序效果代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

javascript中SetInterval与setTimeout的定时器用法

Javascript的setTimeOut和setInterval函数应用非常广泛,它们都用来处理延时和定时任务,比如打开网页一段时间后弹出一个登录框,页面每隔一段时间发送异步请求获取最新数据等,本文文章通过代码示例给大家介绍javascript中SetInterval与setT
收藏 0 赞 0 分享

jquery带下拉菜单和焦点图代码分享

这篇文章主要介绍了jquery带下拉菜单和焦点图代码,推荐给大家,有需要的小伙伴可以参考下。
收藏 0 赞 0 分享

jQuery实现的背景动态变化导航菜单效果

这篇文章主要介绍了jQuery实现的背景动态变化导航菜单效果,涉及jquery页面元素背景动态变换的实现技巧,非常具有实用价值,需要的朋友可以参考下
收藏 0 赞 0 分享

jquery+CSS实现的水平布局多级网页菜单效果

这篇文章主要介绍了jquery+CSS实现的水平布局多级网页菜单效果,涉及jquery页面元素属性动态变换效果实现技巧,非常具有实用价值,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多