阅读 42

hook:deactivated

一般情况下清除定时器
export default {
    data(){
        return {
            timer:null // 接收定时器返回值
        }
    },
    mounted(){
       this.timer = setInterval(() => {
           console.log('开始定时器')
       },1000)
    },
    beforeDestory(){
        clearInterval(this.timer)
    }
}
复制代码

这段代码是最常见的,也是我平时写的,每次写都不会考虑很多,总觉得这样就可以了,但是其中可以发现几个不好的问题:

  • clearInterval后没有清空timer为null
  • 开启定时器和清除定时器的代码分散开在两个地方,有损可读性/维护性,用大大大佬的话说,这使得我们比较难于程序化地清理我们建立的东西
  • timer被定义在data里,实际上timer不需要什么响应操作,定义在data里是没必要的,反而造成性能浪费。
优化清除定时器
export default {
    data(){
        return {}
    },
    mounted(){
        let timer =setInterval(() => {
            console.log('开始定时器')
        },1000)
        
        this.$once('hook:beforeDestory',() => {
            clearInterval(timer)
            timer=null
        })
    }
}
复制代码

这里使用hook监听beforeDestroy生命周期,这样timer只需被定义在生命周期里,以上的问题就全部解决了。

衍生问题:beforeDestroy是否会不触发?

当路由使用keep-alive缓存时是不走beforeDestroy生命周期的,所以实际上定时器没有被清除掉。我们要借助activated和deactivated这两个钩子:

export default {
    data(){
        return {}
    },
    mounted(){
        let timer=setInterval(() => {
            console.log('开启定时器')
        },1000)
        
        this.$on('hook:activated',() => {
            // 避免重复开启定时器
            if(timer===null){
                timer=setInterval(() => {
                    console.log('开启定时器')
                },1000)
            }
        })
        
        this.$on('hook:deactivated',() => {
            clearInterval(timer)
            timer=null
        })
    }
}
复制代码

这里可以看出,将once换成了once换成了on,是因为缓存的原因,不然执行一次后就不会触发了。

文章分类
前端
文章标签