简介
一般地,双向绑定多用于表单这类输入组件,但在非表单组件上使用双向绑定的需求也很常见,比如具有单选性质的菜单、标签页等组件,通过双向绑定可以更方便地获取和修改激活项。
之前常用的方法是通过 .sync 修饰符绑定 value 属性,并在组件内部触发 emit('update:value',newValue) 的形式,但还是不够优雅。
最近看 element 源码时发现一个小技巧,value 作为 prop 不变,但触发的自定义事件换成 input,此时就可以通过 v-model 指令代替 .sync 修饰符。
简单说明
v-model 原本是针对表单中输入组件的语法糖,根据输入组件的不同,其内部会触发相应的自定义事件,比如文本框组件就会触发 input 事件。而这里是在非表单组件内部触发 input 事件,也能搭配 v-model 实现双向绑定,说明 v-model 指令被编译成 :value="yourValue" @input=value => yourValue = value"
时,并不需要 100% 判定这是一个表单输入组件,否则的话这里的编译应该是无法通过的。
查看相关源码,发现若是在组件上使用 v-model 指令,编译时确实是直接将其编译为一个名为 value 的 prop 和一个 input 事件。
因此,在非表单输入组件内部使用 input 作为自定义事件,确实是有效的。
当然,还是建议只在绑定简单的数据类型时使用,比如数字、字符串等类型,因为它们很少会有非“整值替换”的变化;复杂的对象还是通过 v-bind + @event 显示声明的方式绑定,因为对象大多只是替换其中的某个属性,甚至是嵌套对象的属性,通过事件自定义修改会更方便。
具体的源码分析可以查看以下链接:
(vue2):https://blog.csdn.net/weixin_43294560/article/details/122585166
(vue3):https://blog.csdn.net/fegus/article/details/125757003
本地查看 v-model 源码:
vue2 中位于 node_modules/vue/dist/vue.js
vue3 应该是 node_modules/vue/dist/vue.global.js