$emit与v-on的配合
解释:
vm.$emit(eventName, [...args])
,是触发当前实例上的事件,附加参数都会传给监听器回调。意思是可以触发事件,并把触发的参数回调给监听器(v-on)v-on
,绑定事件监听器,接受$emit的回调参数。
举个例:
孩子需要找父母要钱,父母那有10000元,孩子每花一次钱就花100元,就要从10000元减去100,实现这个需求!
子组件
<template>
<div class="child">
{{money}}
//孩子组件需要告诉父组件要花100元,即触发这个名为“update:money”的事件
<button @click="$emit('update:money', money-100)">
<span>花钱</span>
</button>
</div>
</template>
<script>
export default {
props: ["money"]
};
</script>
<style>
.child {
border: 3px solid green;
}
</style>
父组件:
<template>
<div class="app">
App.vue 我现在有 {{total}}
<hr>
//父组件监听孩子组件触发了什么事件
<Child :money="total" v-on:update:money="total = $event"/>
</div>
</template>
<script>
import Child from "./Child.vue";
export default {
data() {
return { total: 10000 };
},
components: { Child: Child }
};
</script>
<style>
.app {
border: 3px solid red;
padding: 10px;
}
</style>
结果图:
疑问:为什么孩子组件不直接改父组件的数据呢?如下:
父组件代码不变,孩子组件代码如下:
<template>
...
<button @click="money-=100"> //只改了这行代码,其他不变
...
</template>
...
但这样会报错,因为是不可以更改外部数据的。
所以,Vue有这样的规定:
- 组件不能修改props外部数据。
- this.$emit可以触发事件,并传参。
- $event可以获取$emit的参数。
通俗易懂:
孩子找父母要花100块钱($emit,即需要触发事件并传送参数),父母就会知道孩子要钱(v-on,监听事件并接受参数),于是孩子就可以花钱了(触发事件)!
如果孩子没通过允许去偷钱(更改外部数据),那是不道德的!
.sync
最后,如果觉得:
:money="total" v-on:update:money="total=$event"
很长的话,可以使用 .sync
,替换以上代码,如下:
:money.sync="total"
即可,也就是说,这个代码等价于上面的代码。
:::success
.sync
是 v-on
和 $emit
的语法糖!
:::