sync

前言

当我们在子组件中想要修改通过props绑定的外部组件里的数据时,Vue不支持我们直接在子组件中进行修改,子组件没有修改父组件数据的权力,推荐我们利用EventBus事件中心,在vue实例上就含有$emit接口来触发事件,$on来监听响应事件,$off来移除事件的监听,所以在子组件中使用this.$emit()来触发事件,并把修改后的值作为参数传入,Vue会把传入的参数保存到$event中,父组件响应事件并通过$event来取值实现数据的更新,避免由子组件直接修改父组件传过来的内容。

官方示例

举个例子,在一个包含 title prop 的组件中,通过$emit来触发’update:title’事件,向父组件发送数据更新消息:

this.$emit('update:title', newTitle)

然后父组件中可以监听’update:title’事件并根据需要更新一个本地的数据 property。

<text-document
  v-bind:title="doc.title"
  v-on:update:title="doc.title = $event"
></text-document>

v-on:update:title="doc.title = $event"这一长串在模版中显得十分笨重,而且父子间通信是常用的操作,模版中要是出现很多类似语句就违反了Vue简洁的出发点,所以Vue就推出了sync修饰符~

使用

Vue为上面的模式提供一个缩写,即 .sync 修饰符,.sync 修饰符就是事件绑定的语法糖:

<text-document :title.sync="doc.title"></text-document>

上面的例子通过sync修饰符简化后里面就变得简单明了

示例

下面通过一个父子组件通信的例子来掌握sync修饰符的用法

父组件将money值传给子组件,子组件不能直接修改money值,必须要触发事件来告知父组件修改后的money值,在父组件中监听到事件后确认修改对应的money的值,有v-on的写法和使用sync修饰符简写的语法。

子组件

child.vue

<template>
  <div class="child">
    {{money}}
    <button @click="$emit('update:money', money-100)">
      <span>子组件花100元</span>
    </button>
  </div>
</template>

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


<style>
.child {
  border: 3px solid green;
}
</style>

父组件

app.vue

<template>
  <div class="app">
    父组件:我现在有 {{total}}元
    <hr>
    <!-- 语法糖式写法 -->
    <!-- <Child :money.sync="total"/> -->
    <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>
  • 事件的名称最好写为update:mondyupdate是vue规定的语法书写格式,money是被绑定事件的属性。
  • 代码会被扩展成(自动更新父组件属性的 v-on 监听器),就是一个语法糖。

vue3升级改变

在 Vue 2.0 中, v-model 指令只能为 value 的 prop进行双向绑定,但如果我们对其他的 prop进行双向,就不得不使用 v-bind.sync,如上面实例中的money

在vue3对v-model做出了升级改变!

在 Vue 3 中,双向数据绑定的 API 已经标准化,减少了开发者在使用 v-model 指令时的混淆并且在使用 v-model 指令时可以更加灵活。

所以上例父组件中:

原始版本:

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

使用v-bind.sync

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

vue3中使用v-model

<Child v-model:money="total"/>

参考官方文档:vue3:v-model