Vue2 的 v-model、.sync、自定义事件有什么关系?
先理解原理和示例,再练习完整口述与追问。
回答要点
组件默认 v-model 对应 value prop 和 input 事件,可通过 model 配置调整;.sync 对应 update:属性名 事件。它们都是输入加更新通知的约定,不意味着子组件能随意修改父状态。
原理拆解
Vue2 自定义组件默认 v-model 是 value prop 与 input 事件的语法糖,组件可以用 model 选项修改对应名称。.sync 通常展开为一个 prop 加 update:propName 监听,适合显式同步某个属性。两者本质仍是父传值、子发事件,不是子组件获得了修改父状态的特殊权限。原生输入框与组件 v-model 的编译细节应分别说明。
示例与推演
export default {
props: { value: String },
methods: {
change(value) { this.$emit('input', value) }
}
}
父级 <Editor v-model="name" /> 可理解为传 :value="name" 并在 input 时更新 name;:visible.sync 对应子组件发 update:visible。
易错点
Vue3 默认改为 modelValue/update:modelValue,多模型与修饰符能力也不同。不要把 Vue3 的 defineModel 宏写进 Vue2 组件实现。
参考回答可直接练习口述
Vue2 组件 v-model 默认是把值传给 value prop,并监听 input 事件更新父状态;组件可以通过 model 选项更改这组名字。.sync 是另一种语法简化,例如 :visible.sync 对应 visible 输入和 update:visible 通知。底层仍是单向输入加显式事件,所以我封装组件时会先定义清楚值类型、更新事件和校验行为。
面试官可能继续问追问与完整解答展开收起
追问
封装输入组件如何透传原生事件?为什么自定义事件不会像 DOM 事件一样自动向祖先冒泡?Vue2 官方自定义事件
追问回答
封装原生输入框时,可用 $listeners 有选择地把事件传到真实 input,并用 $attrs 透传非 prop 属性;要避免重复绑定相同事件。组件自定义事件只被直接监听该事件的父级接收,不按 DOM 冒泡规则自动传播到祖先,需要显式转发。