# 前言
众所周知,单向数据流导致我们不能在子组件不能变更父组件
实际开发中我们常用引用类型数据来违规修改父组件但是不太好
vue 在 2.3.0+ 新增了 .sync
修饰符,实际上是一个语法糖
本篇文章使用的是 vue3
# vue2 示例
子组件给父组件传递数据
this.$emit('update:title', newTitle) |
父组件通过事件接受
<text-document :title="doc.title" @update:title="doc.title = $event"></text-document> |
为了方便起见,我们为这种模式提供一个缩写,即 .sync
修饰符:
<text-document :title.sync="doc.title"></text-document> |
一个对象设置多个 prop 也可以配合使用,这样会把 doc 对象中的每一个 property (如 title) 都作为一个独立的 prop 传进去,然后各自添加用于更新的 v-on 监听器
<text-document v-bind.sync="doc"></text-document> |
注意带有 .sync 修饰符的 v-bind 不能和表达式一起使用 (例如 v-bind:title.sync=”doc.title + ‘!’” 是无效的)。取而代之的是,你只能提供你想要绑定的 property 名,类似 v-model。将 v-bind.sync 用在一个字面量的对象上,例如 v-bind.sync=”{ title: doc.title }”,是无法正常工作的,因为在解析一个像这样的复杂表达式的时候,有很多边缘情况需要考虑。
# vue3 示例
在 3.x 中修饰符语法有所改变,不再用 v-bind 而用 v-model
<ChildComponent v-model:title="pageTitle" /> | |
<!-- 是以下的简写: --> | |
<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" /> |
父组件
<Dialog v-model:visible="visible" :title="title"> </Dialog> |
子组件
<button @click="close">关闭对话框</button> | |
export default { | |
name: 'Dialog', | |
props: ['visible', 'title'], | |
emits: ['update:visible'], | |
setup(props, context) { | |
function close() { | |
context.emit('update:visible', !props.visible) | |
} | |
return { | |
close | |
} | |
} | |
} | |
</script> |
# 小结
子组件变更父组件,使用 .sync
的父组件会直接赋值,省去了监听触发事件这一步操作
在父组件中给某一个属性 prop 添加 .sync
,那么在子组件直接使用 update:propName
自定义事件给父组件,而父组件都不需要监听这个事件去得到子组件修改后的数据