Vue 3 中 .sync 修饰符已被移除,由 v-model:propName 机制替代;需子组件显式声明 defineEmits 并触发 update:propName 事件,支持多个独立 v-model 绑定。

Vue 3 中 .sync 修饰符已被移除,不再支持。它不是“失效”,而是被更清晰、更可扩展的 v-model:xxx 机制完全替代。核心思路是:每个需要双向同步的 prop,都配一个独立的 v-model:propName,子组件通过 update:propName 事件通知父组件更新。
用 v-model:xxx 替代 :prop.sync
原来 Vue 2 的写法:
<MyDialog :visible.sync="show" :title.sync="dialogTitle" />
在 Vue 3 中等价写法是:
立即学习“前端免费学习笔记(深入)”;
<MyDialog v-model:visible="show" v-model:title="dialogTitle" />
这会自动编译为:
<MyDialog :visible="show" :title="dialogTitle" @update:visible="val => show = val" @update:title="val => dialogTitle = val" />
子组件只需按约定 emit 对应事件即可完成同步。
Vue 3 组合式 API 与 最佳实践,涵盖代码组织、useXxx 模式、组合式函数设计、Store 集成、响应式优化及功能抽取。
子组件需显式声明并触发 update:xxx 事件
子组件中必须:
- 用
defineProps接收对应 prop(如visible、title) - 用
defineEmits显式声明要触发的事件(如'update:visible'、'update:title') - 在需要更新时调用
emit('update:visible', newValue)
示例(Composition API):
const props = defineProps({ visible: Boolean, title: String });
const emit = defineEmits(['update:visible', 'update:title']);
// 关闭弹窗时
const handleClose = () => emit('update:visible', false);
// 修改标题时
const handleTitleChange = (newVal) => emit('update:title', newVal);
多个 v-model 可共存,互不干扰
Vue 3 支持任意数量的 v-model:xxx,每个都独立工作:
-
v-model:visible控制显隐 -
v-model:disabled控制禁用状态 -
v-model:filters同步筛选条件对象 - 甚至可以搭配
v-model(默认 modelValue)一起用:<MyInput v-model="text" v-model:placeholder="hint" />
所有这些绑定都遵循同一套规则:prop 名 → update:propName 事件 → 父组件响应赋值。
注意命名规范和类型安全
推荐使用 kebab-case 命名 prop(如 user-id),对应事件为 update:user-id;但注意 JS 中不能直接写带短横线的属性名,需用引号包裹:
defineEmits(['update:user-id', 'update:is-open'])
搭配 TypeScript 时,defineEmits 的类型声明能提供完整事件校验,避免拼写错误或遗漏事件,这是 .sync 时代不具备的优势。

















