前言
当我们在子组件中想要修改通过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:mondy,update是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