本文首发于我的个人博客
本篇文章记录了作者在使用Vue+Axios实现前端自动刷新数据时,遇到的一个坑点。
场景需求
在一个Vue单页应用中,使用VueRouter实现了App组件中点击链接后呈现Component组件的功能
App.Vue -> Component.Vue
现在需要:在Component加载出来之后,每间隔1s的时间,自动通过Axios向后端接口获取数据并更新。
有问题的实现方式
App.Vue,内置router-link,可以跳转呈现Component
// App.Vue
<template>
<div>
<router-link :to="/Component">Component</router-link>
<router-view></router-view>
</div>
</template>
Component.Vue,在创建时,使用setInterval
创建1s中的循环动作,在动作中使用Axios获取后端数据
// Component.Vue
<template>
<div></div>
</template>
<script>
export default {
created() {
// 设置一个间隔1s就进行的动作
setInterval(() => {
Axios.get("/data").then((res) => {
// 业务逻辑
})
}, 1000)
}
}
</script>
问题分析
出现问题的原因在于:
只有setInterval
,没有clearInterval
一个循环任务一旦被创建,就没有被销毁的可能,但是每次用户点击Component
链接,都会创建Component
实例,产生循环任务。
如果用户多次点击了App.Vue
中的Component
链接,那么就会在前端浏览器里产生多个循环任务,不断发送请求,最终导致前后端都不堪重负。
解决方案
通过data
记录created
中产生的循环任务,并在beforeDestroy
里加入clearInterval
清除它。
// Component.Vue
<template>
<div></div>
</template>
<script>
export default {
data() {
return {
timer : {},
}
},
created() {
// 设置一个间隔1s就进行的动作
this.timer = setInterval(() => {
Axios.get("/data").then((res) => {
// 业务逻辑
})
}, 1000)
},
beforeDestroy() {
clearInterval(this.timer)
}
}
</script>