$emit与v-on的配合

解释:

  • vm.$emit(eventName, [...args]) ,是触发当前实例上的事件,附加参数都会传给监听器回调。意思是可以触发事件,并把触发的参数回调给监听器(v-on)
  • v-on ,绑定事件监听器,接受$emit的回调参数。

举个例:

孩子需要找父母要钱,父母那有10000元,孩子每花一次钱就花100元,就要从10000元减去100,实现这个需求!

子组件

  1. <template>
  2. <div class="child">
  3. {{money}}
  4. //孩子组件需要告诉父组件要花100元,即触发这个名为“update:money”的事件
  5. <button @click="$emit('update:money', money-100)">
  6. <span>花钱</span>
  7. </button>
  8. </div>
  9. </template>
  10. <script>
  11. export default {
  12. props: ["money"]
  13. };
  14. </script>
  15. <style>
  16. .child {
  17. border: 3px solid green;
  18. }
  19. </style>

父组件:

  1. <template>
  2. <div class="app">
  3. App.vue 我现在有 {{total}}
  4. <hr>
  5. //父组件监听孩子组件触发了什么事件
  6. <Child :money="total" v-on:update:money="total = $event"/>
  7. </div>
  8. </template>
  9. <script>
  10. import Child from "./Child.vue";
  11. export default {
  12. data() {
  13. return { total: 10000 };
  14. },
  15. components: { Child: Child }
  16. };
  17. </script>
  18. <style>
  19. .app {
  20. border: 3px solid red;
  21. padding: 10px;
  22. }
  23. </style>

结果图:
image.png

疑问:为什么孩子组件不直接改父组件的数据呢?如下:

父组件代码不变,孩子组件代码如下:

  1. <template>
  2. ...
  3. <button @click="money-=100"> //只改了这行代码,其他不变
  4. ...
  5. </template>
  6. ...

但这样会报错,因为是不可以更改外部数据的。

所以,Vue有这样的规定:

  • 组件不能修改props外部数据。
  • this.$emit可以触发事件,并传参。
  • $event可以获取$emit的参数。

通俗易懂:

孩子找父母要花100块钱($emit,即需要触发事件并传送参数),父母就会知道孩子要钱(v-on,监听事件并接受参数),于是孩子就可以花钱了(触发事件)!

如果孩子没通过允许去偷钱(更改外部数据),那是不道德的!

.sync

最后,如果觉得:

  1. :money="total" v-on:update:money="total=$event"

很长的话,可以使用 .sync ,替换以上代码,如下:

  1. :money.sync="total"

即可,也就是说,这个代码等价于上面的代码。

:::success .syncv-on$emit 的语法糖! :::

简单例子

Vue传值—三种常用传值