定时器
看到过一个 Vue 开发技巧,讲的是关于处理组件内定时器的步骤。
通常我们一般都是这样操作的:
<script>
export default {
data() {
return {
timer: null
}
},
mounted() {
this.timer = setInterval(() => {
... }, 1000)
},
beforeDestroy() {
clearInterval(this.timer)
this.timer = null
}
}
</script>
但是其实更好的做法是:
<script>
export default {
mounted() {
const timer = setInterval(() => {
... }, 1000)
this.$once('hook:beforeDestroy', () => clearInterval(timer))
}
};
</script>
vm.$once( event, callback )
参数:
{string} event
{Function} callback
用法:监听一个自定义事件,但是只触发一次。一旦触发之后,监听器就会被移除。
语法
从语法上来看,就是组件内的生命周期函数在执行结束后会 $emit
一个"hook + 生命周期名字
" 的自定义事件。
子组件内部监听
这样的话,我们就可以在一个生命周期方法里监听其余生命周期的发生(如上例所示)。
一些情况下确实可以达到优化或简化代码的效果。比如处理组件内多个生命周期的逻辑变得非常简单,简单到只有一句时,这个时候就可以考虑将这些代码放在 created 或者 mounted 里通过这种方式来监听并执行那些简单逻辑。
父组件对子组件监听
当组件内的生命周期函数在执行结束后 $emit 的自定义事件。不仅仅可以在组件内被 $on。vue 的语法决定了这些事件也可以被父组件 v-on 到。
设想一个需求场景:
一个页面里需要加载一个可视化组件,这个组件里面的逻辑极其复杂,存在大量复杂的计算。因为考虑可能要在多个地方使用,就并没有引入主题相关的 loading。我们的需求是什么呢?
就是在数据渲染到页面的之前让页面 loading。mounted 之后停止 loading。beforeUpdata 时开始 loading。updatad 之后停止 loading。
最简单的方法就是改写组件的生命周期函数,使其在 mounted/beforeUpdata/updatad 时通知父组件显示或者隐藏 loading。
这样做显然不好,因为侵入了子组件的逻辑,增加的逻辑也和组件本身的功能好不关联。最好的办法就是使用 v-on=“hook:xxx” 的方式:
<v-chart
@hook:mounted="loading = false"
@hook:beforeUpdated="loading = true"
@hook:updated="loading = false"
:data="data"
/>
这样,就实现了对子组件生命周期的监听。对任意的组件都有效果,包括引入的第三方组件。