官方文档:程序化的事件侦听器 (opens new window)
$emit方法是传入事件名称来触发一个事件,它可以被v-on侦听,但是Vue实例同时在其事件接口中提供了其它的方法。我们可以:
- 通过
$on(eventName, eventHandler)侦听一个事件 - 通过
$once(eventName, eventHandler)一次性侦听一个事件 - 通过
$off(eventName, eventHandler)停止侦听一个事件
官方文档中的例子是某个组件的创建与销毁,我们更常用的是定时器和添加事件销毁事件
export default {
name: 'Temp',
data() {
return {
timer: null,
};
},
mounted() {
this.timer = setInterval(() => {
// 具体执行内容
}, 1000);
},
beforeDestory() {
clearInterval(this.timer);
this.timer = null;
},
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
这种方法存在的问题是:
它需要在这个组件实例中保存这个
timer,如果可以的话最好只有生命周期钩子可以访问到它。这并不算严重的问题,但是它可以被视为杂物。创建的定时器代码和销毁定时器的代码没有放在一起,通常很容易忘记去清理这个定时器,不容易维护。这就是文档里说的:
我们的建立代码独立于我们的清理代码,这使得我们比较难于程序化地清理我们建立的所有东西。
所以我觉得这就是为啥叫程序化的事件侦听器
解决方法:可以用hook来监听beforeDestory生命周期。因为只要监听一次就够了,所以用$once来注册监听。
export default {
name: 'Temp',
data() {
return {};
},
mounted() {
const timer = setInterval(() => {
// 具体执行代码
console.log('1');
}, 1000);
this.$once('hook:beforeDestory', () => {
clearInterval(timer);
});
},
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
事件的绑定与移除
export default {
mounted() {
// 监听窗口发生变化,resize组件
window.addEventListener('resize', this.resizeFunc);
// 通过hook监听组件销毁钩子函数,并取消监听事件
this.$once('hook:beforeDestroy', () => {
window.removeEventListener('resize', this.resizeFunc);
});
},
};
2
3
4
5
6
7
8
9
10
文档里面还有一个说明:
WARNING
注意Vue的事件系统不同于浏览器的EventTarget API (opens new window)。尽管它们工作起来是相似的,但是$emit、$on,和$off并不是dispatchEvent、addEventListener和removeEventListener的别名。
事件监听器还有一个重要的用法,在父组件监听子组件的生命周期方法
场景:父组件如何在子组件的生命周期里做某些处理?例如子组件更新了,但是没有提供change事件,又或者需要在子组件加载更新阶段增加或移除loading效果等
方法一:修改子组件源码,在子组件生命周期中emit父组件
子组件
export default {
name: 'Child',
mounted() {
this.$emit('callParent');
},
};
2
3
4
5
6
父组件
<template>
<div>
<Child @callParent="childCall" />
</div>
</template>
<script>
export default {
name: 'Parent',
methods: {
childCall() {},
},
};
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
方法二:在父组件中使用hook,无需修改子组件
<template>
<div>
<Child @hook:mounted="childCall" />
</div>
</template>
<script>
export default {
name: 'Parent',
methods: {
childCall() {},
},
};
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14