分类
Javascript

双向绑定Vue自定义组件

React和Vue都主张组件之间交互用单向数据流,这样更SOLID的设计原则。但很多时候我们还是要用到双向数据流,也就是大家所说的MVVM,一个很特殊的场景就是表单处理,使用双向数据绑定还是方便很多。和Andular一样,Vue也可以通过v-module指令支持幽微数据绑定。很多情况下,我们都需要自定义组件,以输入表单为例,怎样实现自定义组件双向数据绑定呢?

一、使用props/$emit

该方法通过在组件中声明任意属性,再派发任意自定义事件来实现。接收组件实例还得绑定组件属性,编写自定义事件处理函数方法。可以参考工程代码中的EventDemo.vue。本实例中,声明了message属性,再在current计算属性set方法中派发update事件。

注意

为什么不通过change事件方法来派发update事件呢?因为我们在组件内部使用了v-model,v-model不能绑定props属性。Eslint会告警不能直接修改props属性,还有异步不能更新赋值的问题,感兴趣的同学可以参考AsyncIssue.vue。如果改用vlaue绑定props属性,再通过change事件方法来派发也是可以的。

二、自定义v-model

这个方法在Vue指南相关章节写得很清楚了。它其实是props/$emit方式的派生。对于输入表单组件,设置的属性名一定要是value,派发的自定义事件名一定要是input。可以参考工程代码中的ValueDemo.vue。该实例中,我们为组件设置了vue属性并派发了input事件。

注意

请记住!属性名和定义事件名按照约定的设定才能让自定义组件支持v-model,不然就只是普通双向数据绑定了。虽然普通双向数据绑定不局限于属性名事件名更灵活一点,但用起来还是没v-model方便,对吧?

另外,工程代码提供了其它两个版本的自定义v-model,还是那个原因:组件内部使用了v-model,v-model不能绑定vue属性,所以通过计算属性和Watch侦听器来实现。感兴趣的同学可以参考ComputedDemo.vueWatchDemo.vue

三、自定义sync修饰符

从Vue 1.0开始,在组件实例属性上添加sync修饰符也可以实现自定义组件双向数据绑定。具体用法Vue指南相关章节介绍得很详细了。和自定义组件的v-model一样,它也只是props/$emit方式的派生。设置的属性名可以任意,派发的自定义事件一定要是update:[属性名]。详细代码清单可以参考工程中的SyncDemo.vue。该实例中,我们为组件设置了message属性并派发了update:message事件。

注意

Element UI的el-dialog组件就是一个通过自定义visible属性的sync修饰符来控制弹窗的显示隐藏的。

四、使用props对象

该方法需要在组件中声明对象属性,将对象属性绑定到输入表单的Vlaue属性,接着派发了input事件。它其实也是props/$emit方式的派生,适用于要双向数据绑定多个属性。详细代码清单可以参考工程中的ObjectDemo.vue

注意

不建议直接将对象属性通过v-model绑定到输入表单上,v-model双向绑定props后会修改它的值,这会导致不可意料的Bug。Element UI的el-form在外层将整个props对象绑定到model上,会将表单项的prop属性设定为相应的对象属性名,使用v-model双向绑定表单相应的对象属性值。这样设计很nice,使用起来也很方便。