如何理解 Vue 的 .sync 修饰符

92 阅读1分钟

.sync修饰符是Vue提供的语法糖,它会被扩展成修改父组件属性的监听器。应用场景是在父子组件传值,且子组件要修改这个数据的时候使用。在Vue中有一条规定,组件不能直接修改props外部传来的数据,合理的做法是子组件通知父组件,由父组件进行数据的修改。它的原理是利用EventBus,子组件触发事件,父组件响应事件并实现数据的更新。

用一个通俗的例子来解释,孩子向爸爸借钱,爸爸并不会直接把钱交给孩子随意支配,而是告诉孩子我手头上有这么多钱,你需要花钱的时候通知我需要支付的金额,我帮你付款。

用一段代码来模拟上面的场景

子组件

<template>
  <div class="child">
    <button @click="$emit('update:money', money - 100)">
      <span>我要花100块钱买玩具</span>
    </button>
  </div>
</template>

<script>
export default {
  props: ["money"],
};
</script>

父组件

<template>
  <div class="app">
    <!-- $event接收事件抛出的值 -->
    <Child :money="total" v-on:update:money="total = $event" />
    <!-- .sync语法糖 <Child :money.sync="total" /> -->
  </div>
</template>

<script>
import Child from "./Child.vue";
export default {
  components: { Child: Child },
  data() {
    return { total: 10000 };
  },
};
</script>

实现的原理是利用eventBus,在子组件使用$emit 来通知父组件去响应,而父组件则通过$event来接收经过子组件修改后的值。

注意事件名必须写为update:xxxxxx是修改的属性名,也就是money

.sync可将

<Child :money="total" v-on:update:money="total = $event" />

简写为

<Child :money.sync="total" />

再解释一下$event

$event保存了通过事件抛出的值,父组件监听这个事件的时候就可以通过$event访问这个值,如果事件处理函数是一个方法,那么这个值会作为第一个参数传入方法,也就是说上面代码也可以写成

<Child :money="total" v-on:update:money="(restMoney) => total = restMoney" />