.sync 修饰符
在 Vue 2 中,.sync 修饰符是实现父子组件双向数据绑定的语法糖,特别适合用于弹窗这类需要子组件修改父组件状态的场景。
基本概念
.sync 修饰符,实际上就是将父组件的属性,通过 .sync 修饰符,映射到子组件的 props 属性中,并监听子组件的 props 属性的修改,将修改后的值,通过 $emit 事件发送给父组件,从而实现父子组件的数据同步。
本质是自动为你扩展了一个 v-on 监听器。
html
<!-- 使用 .sync 的写法 -->
<ChildComponent :visible.sync="dialogVisible" />
<!-- 等效于完整写法 -->
<ChildComponent
:visible="dialogVisible"
@update:visible="val => dialogVisible = val"
/>
举例
1. 引入并注册弹窗组件
javascript
import MyDialog from "./MyDialog.vue";
export default {
components: {
MyDialog,
},
data() {
return {
showDialog: false,
};
},
};
2. 注册点击事件并绑定弹窗组件
html
<template>
<div class="parent">
<button @click="showDialog = true">打开弹窗</button>
<!-- 使用 .sync 修饰符 -->
<MyDialog :visible.sync="showDialog" title="示例弹窗" />
</div>
</template>
3. 子组件:弹窗逻辑
3.1 定义接收的 props
javascript
props: {
visible: {
type: Boolean,
default: false
},
title: {
type: String,
default: '弹窗标题'
}
},
3.2 使用 v-if 控制弹窗显示
html
<div class="dialog-overlay" v-if="visible">
<div class="dialog-content">
<div class="dialog-header">
<h3>{{ title }}</h3>
<button class="close-btn" @click="closeDialog">×</button>
</div>
<div class="dialog-body">
<p>这是一个弹窗内容</p>
<slot></slot>
<!-- 支持插槽内容 -->
</div>
<div class="dialog-footer">
<button @click="closeDialog">取消</button>
<button @click="confirm">确定</button>
</div>
</div>
</div>
3.3 关闭弹窗逻辑
javascript
methods: {
closeDialog() {
// 关键:使用 update:visible 模式触发事件
this.$emit('update:visible', false);
},
confirm() {
console.log('确认操作');
this.closeDialog();
}
},
3.4 监听 visible 变化(可选)
javascript
watch: {
// 监听 visible 变化,处理外部对弹窗的关闭
visible(newVal) {
if (!newVal) {
// 弹窗关闭时的清理操作
}
}
}
详细代码
父组件(使用弹窗)
html
<template>
<div class="parent">
<button @click="showDialog = true">打开弹窗</button>
<!-- 使用.sync修饰符 -->
<MyDialog :visible.sync="showDialog" title="示例弹窗" />
</div>
</template>
<script>
import MyDialog from "./MyDialog.vue";
export default {
components: {
MyDialog,
},
data() {
return {
showDialog: false,
};
},
};
</script>
子组件弹窗(MyDialog.vue)
html
<template>
<div class="dialog-overlay" v-if="visible">
<div class="dialog-content">
<div class="dialog-header">
<h3>{{ title }}</h3>
<button class="close-btn" @click="closeDialog">×</button>
</div>
<div class="dialog-body">
<p>这是一个弹窗内容</p>
<slot></slot>
<!-- 支持插槽内容 -->
</div>
<div class="dialog-footer">
<button @click="closeDialog">取消</button>
<button @click="confirm">确定</button>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
visible: {
type: Boolean,
default: false,
},
title: {
type: String,
default: "弹窗标题",
},
},
methods: {
closeDialog() {
// 关键:使用update:visible模式触发事件
this.$emit("update:visible", false);
},
confirm() {
// 执行确认操作...
console.log("确认操作");
this.closeDialog();
},
},
watch: {
// 监听visible变化,处理外部对弹窗的关闭
visible(newVal) {
if (!newVal) {
// 弹窗关闭时的清理操作
}
},
},
};
</script>
<style scoped>
// 样式
</style>
总结
-
.sync的作用:- 实现父子组件双向绑定,简化代码。
- 特别适合弹窗等需要频繁切换显示状态的场景。
-
核心逻辑:
- 父组件通过
.sync将状态传递给子组件。 - 子组件通过
$emit('update:visible', value)修改父组件的状态。
- 父组件通过
-
可选功能:
- 如果需要在弹窗关闭时执行清理操作,可以使用
watch监听visible的变化。
- 如果需要在弹窗关闭时执行清理操作,可以使用
-
使用场景:
-
弹窗显示/隐藏控制
-
表单编辑对话框
-
确认对话框
-
设置面板
-
任何需要子组件修改父组件状态的场景
-