.sync 修饰符是Vue编译时的语法糖,用于实现对 prop 进行“双向绑定”。 根据官方文档, .sync 在Vue 1.0 版本中存在,但在 2.0 中被移除,由于在实际开发中依旧有 .sync 的适用之处,从 Vue 2.3.0 起又重新引入了 .sync 修饰符,但是这次 .sync 只是作为一个编译时的语法糖存在。
先来一个弹窗的关闭事件案例:
<template>
<div class="details">
<!-- :show.sync='valueChild' 等价于
:show='valueChild' @update:show='val => valueChild = val'
-->
<myComponent :show.sync='valueChild'
style="padding: 30px;border:1px solid #ddd;margin-bottom:10px;">
</myComponent>
<button @click="changeValue">toggle</button>
</div>
</template>
<script>
import Vue from 'vue'
//弹窗子组件
Vue.component('myComponent', {
template: `<div v-if="show">
<p>默认初始值是{{show}},所以是显示的</p>
<button @click.stop="closeDiv">关闭</button>
</div>`,
props:['show'],
//子组件接收父组件的'show'值
methods: {
closeDiv() {
this.$emit('update:show', false);
//在子组件内点击,触发 input 事件,将变化同步到父组件
}
}
})
//父组件
export default{
data(){
return{
valueChild:true,
}
},
methods:{
changeValue(){
this.valueChild = !this.valueChild
}
}
}
</script>
在案例中,子组件改变了父组件的传入值,并且将改变后的值传回了父组件。
因为父组件会依据内部数据的改变而渲染组件,所以子组件可以直接修改父组件的数据时,会造成重复渲染。因此如果希望实现子组件以及父组件的“双向绑定”,那么需要通过 props 将传初始值传入子组件,再对子组件进行事件监听。
.sync 修饰符就是对上面模式的简写。
<comp :foo.sync="bar"></comp>
采用 .sync 的语句会被扩展为:
<comp :foo="bar" @update:foo="val => bar = val"></comp>
而子组件需要更新 foo 的值时,子组件需要显式地触发一个更新事件:
this.$emit('update:foo', newValue)
Vue的编译器会将子组件$emit('update:foo', newValue)的第二个参数自动地绑定到父组件.sync修饰的变量上。