Vue $emit() 方法
使用 Vue 中内置的 $emit()
方法,我们可以在子组件中创建一个自定义事件,该事件可以在父元素中捕获。
传递属性用于将数据从父元素发送到子组件,而 $emit()
用于执行相反的操作:将信息从子组件传递到父组件。
我们的目标 是将食物项目的“收藏”状态更改在父级 App.vue
中,而不是在当前更改发生的子组件 FoodItem.vue
中。
更改收藏状态的原因 是因为 App.vue
是最初存储收藏状态的地方,因此需要更新它。在更大的项目中,数据可能来自我们与 App.vue
中连接的数据库,并且我们希望组件中的更改能够更改数据库,因此我们需要从子组件向父组件进行通信。
发出自定义事件
需要将信息从组件发送到父组件,我们使用内置方法 $emit()
来实现这一点。
我们已经在 FoodItem.vue
组件内部拥有 toggleFavorite
方法,该方法在点击切换按钮时运行。现在,让我们删除现有的行并添加一行来发出我们的自定义事件“toggle-favorite”。
FoodItem.vue
:
methods: {
toggleFavorite() {
this.foodIsFavorite = !this.foodIsFavorite;
this.$emit('toggle-Favorite');
}
}
我们可以选择自定义事件的名称,但通常对于发出事件使用连字符分隔的小写形式。
接收发出事件
自定义发出事件“toggle-favorite”现在从 FoodItem.vue
组件发出,但我们需要在创建组件的父组件 App.vue
中监听该事件,并调用执行某些操作的方法,以便我们可以看到事件发生了。
我们在 App.vue
中使用简写符号 @
而不是 v-on:
来监听事件。
示例
在 App.vue
中监听“toggle-favorite”事件。
<food-item
v-for="x in foods"
:key="x.name"
:food-name="x.name"
:food-desc="x.desc"
:is-favorite="x.favorite"
@toggle-favorite="receiveEmit"
/>
当我们的自定义“toggle-favorite”事件发生时,我们需要在 App.vue
中创建 receiveEmit
方法,以便我们可以看到事件发生了。
methods: {
receiveEmit() {
alert('Hello World!');
}
}
运行示例 »
在父组件中更改食物项目的“收藏”状态
我们现在有一个事件,可以通知 App.vue
子组件中的“收藏”按钮被点击了。
我们想要更改 App.vue
中“foods”数组中正确食物项目的“收藏”属性,当点击“收藏”按钮时。为此,我们从 FoodItem.vue
向 App.vue
发送食物项目名称,因为它是每个食物项目的唯一标识。
FoodItem.vue
:
methods: {
toggleFavorite() {
this.$emit('toggle-favorite', this.foodName);
}
}
我们现在可以在 App.vue
中作为参数接收食物项目名称,该参数传递给在“toggle-favorite”事件发生时调用的方法,如下所示。
现在我们知道点击了哪个食物项目,我们可以在“foods”数组中更新正确食物项目的“收藏”状态。
App.vue
:
methods: {
receiveEmit(foodId) {
const foundFood = this.foods.find(
food => food.name === foodId
);
foundFood.favorite = !foundFood.favorite;
}
}
在上面的代码中,数组方法“find”遍历“foods”数组,并查找名称属性等于我们点击的食物项目的对象,并返回该对象作为“foundFood”。之后,我们可以将“foundFood.health”设置为与其之前状态相反,以便它在 true
和 false
之间切换。
了解更多关于 JavaScript 数组方法“find”的信息,请访问 这里。
了解更多关于 JavaScript 箭头函数的信息,请访问 这里。
现在“foods”数组中的正确食物获得了更新的“收藏”状态。唯一剩下的就是更新指示收藏食物的图像。
由于食物项目组件已经使用来自“foods”数组的“收藏”状态创建,并且作为传递属性“is-favorite”从 App.vue
发送,因此我们只需要在 FoodItem.vue
中从 v-show
引用此“isFavorite”传递属性,其中 <img>
元素用于更新图像。
<img src="/img_quality.svg" v-show="isFavorite">
我们还可以删除 FoodItem.vue
中的 'foodIsFavorite' 数据属性,因为它不再使用。
'emits' 选项
就像我们在 FoodItem.vue
组件中声明 props 一样,我们也可以使用 Vue 的 'emits' 选项来记录组件发出的内容。
Props 必须在组件中声明,而 emits 只是建议记录。
以下是如何在 FoodItem.vue
组件中记录我们的 emit
<script>
export default {
props: ['foodName','foodDesc','isFavorite'],
emits: ['toggle-favorite'],
methods: {
toggleFavorite() {
this.$emit('toggle-favorite', this.foodName);
}
}
};
</script>
当 emits 被记录时,组件更容易被其他人使用。