$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 的语法糖!
:::
