Vue.js 中自定义事件是组件间的一个主要通信方式,尤其是用于子组件向父组件发送消息,在 Vue 2.x 和 Vue 3.x 中自定义事件的概念是基本相同的,但是具体实现方式可能有所不同。
Vue自定义事件是为组件间通信设计, vue中父组件通过prop传递数据给子组件,而想要将子组件的数据传递给父组件,则可以通过自定义事件的绑
触发事件:$emit(eventName, 参数…)
注意:事件名必须用短横线命名方式。
<div id="app">
<!--子组件到父组件-->
<div>
<button-counter v-on:click-test="clickTest"/>
</div>
</div>
var vm = new Vue({
el: '#app',
data: {
ts: new Date().getTime()
},
//对于自定义的button-counter组件, Vue实例为父组件
//在父组件中定义一个test方法,子组件调用该方法
methods: {
clickTest: function(msg) {
console.log("test: "+ msg);
}
},
//局部自定义组件
components: {
//组件名: {配置项}
'button-counter': {
//用来传值的自定义属性
props:['title'],
//模板,模板中写的html代码,在其中可以使用{{}},及指令等vue元素
template: '<button @click="doClick">{{title}}:局部组件,计数:{{count}}</button>',
//注意:在自定义的组件中需要使用函数来定义data
data: function() {
return {
count: 0
}
},
//定义响应事件函数
methods: {
doClick: function() {
//注意此处this的作用返回是自定义组件,而不是上面声明的vue实例.
//注意事件名使用短横线命名方式
this.$emit("click-test","hello vue");
}
}
}
}
});
注意:props定义属性时采用的是驼峰命名法,而在html中使用时需要对应的变为短横线命名法!!
<div id="app">
<!--子组件到父组件-->
<div>
<!-- 注意此处将定义props时的驼峰命名法,变为了短横线命名法 !!! -->
<button-counter title-desc="测试" />
</div>
</div>
var vm = new Vue({
el: '#app',
data: {
ts: new Date().getTime()
},
//对于自定义的button-counter组件, Vue实例为父组件
//在父组件中定义一个test方法,子组件调用该方法
methods: {
clickTest: function(msg) {
console.log("test: "+ msg);
}
},
//局部自定义组件
components: {
//组件名: {配置项}
'button-counter': {
//用来传值的自定义属性
//注意此处使用驼峰命名法 !!!
props:['titleDesc'],
//模板,模板中写的html代码,在其中可以使用{{}},及指令等vue元素
template: '<button @click="doClick">{{titleDesc}}:局部组件,计数:{{count}}</button>',
//注意:在自定义的组件中需要使用函数来定义data
data: function() {
return {
count: 0
}
},
//定义响应事件函数
methods: {
doClick: function() {
//注意此处this的作用返回是自定义组件,而不是上面声明的vue实例.
//注意事件名使用短横线命名方式
this.count ++;
console.log(this.titleDesc);
}
}
}
}
});
以下是自定义事件的详细介绍:
在子组件中,你可以使用 this.$emit
方法发射一个事件,这样父组件可以在模板中使用 v-on
或者 @
来监听这些事件,$emit
方法的第一个参数是事件的名字,后面的参数是传递给监听器的数据。
// 子组件
export default {
methods: {
submitForm() {
// Emit an 'input' event with the new value
this.$emit('form-submit', someValue);
}
}
}
在父组件中,你可以监听这个事件,如同监听原生 DOM 事件一样:
<!-- 父组件 -->
<template>
<my-component @form-submit="handleFormSubmit"></my-component>
</template>
<script>
export default {
methods: {
handleFormSubmit(value) {
console.log('Form submitted with:', value);
}
}
}
</script>
你可以使用 v-on
绑定自定义事件,当你在一个组件的根元素上监听一个事件时,这个事件是由子组件发射出来的,如果你希望在组件内部的某个特定元素上监听事件,你将需要在这个元素上直接使用 v-on
。
有时你可能希望在子组件的根元素上监听一个原生事件,你可以使用 .native
修饰符来达到这个目的,在 Vue 3.x 中已经废除 .native
修饰符,因为 Vue 3 提供了更合适的方式来处理事件。
.once
和 .capture
.once
修饰符可以让事件只触发一次。.capture
修饰符会使用事件捕获模式。如果你要动态地监听或移除事件监听器,你可以在组件的 methods
中定义方法,并在 mounted
或 beforeDestroy
(在 Vue 3.x 中为 beforeUnmount
) 生命周期钩子中添加或移除事件监听器。
export default {
mounted() {
this.$on('my-event', this.doSomething);
},
beforeDestroy() {
this.$off('my-event', this.doSomething);
},
methods: {
doSomething() {
// ...
}
}
}
有时候,你可能需要一个跨越整个应用的方式来通信,事件总线可以帮助你,你可以通过创建一个新的 Vue 实例作为事件中心,在不同的组件间使用它来通信。
// event-bus.js
import Vue from 'vue';
export const EventBus = new Vue();
// 发送事件
EventBus.$emit('my-event', data);
// 监听事件
EventBus.$on('my-event', data => {
// ...
});
不过在 Vue 3 中,由于提供了 Composition API,更推荐使用 Provide/Inject 或者是一个状态管理库如 Vuex 来处理跨组件的状态共享和事件通信。
Vue 自定义事件是 Vue.js 提供的一个非常有用的特性,它可以帮助你的应用中不同组件之间通信和交互,熟练使用自定义事件将是你构建高效 Vue 应用程序的重要技能之一。