Vue参数传递存在一个特点:单向数据流,数据只能从父级传递给子级的,子级无法修改父级的参数(简单地说,就是子级控件无法修改props)。
在做一些功能件的时候,这些限制会产生一些非常差的用户体验。
比如我们有一个组件A,参数是x,组件A经过用户操作,x会产生一个新的值,并且组件A还包含校验算法,需要验证x是否有效。
B组件调用A组件的时候,需要先判断是否有效,只有验证通过才能接收这个新的值。
上述案例,很明显存在一个的问题,B组件很难获取A组件的校验函数(可以通过ref,但是就和写html一样,不到万不得已你不会使用id,这么做总觉得有点不爽)。
方案1:实现v-model
简单的实现方案,就是实现自定义组件的v-model功能,缺点就是v-model只能绑定一个值。
方案2:使用provide
使用provide,可以将父级组件的参数,传递给子级组件,这时候,子级组件可以直接修改参数值,通过这一个特性,可以实现非常多传统的编程。
父级控件
通过provide,将自己的参数传递到子级控件。
<script>
import FormInput from './FormInput.vue'
export default {
name: "fast-form"
, provide() {
return {
formGroup: this.formGroup
};
}
}
<script>
子级控件
通过inject接收父级传递的参数,通过给参数增加函数回调,子级控件可以将内部的数据,直接传递回父级控件。
(正常的开发,我们应当遵循VUE的规范,这种写法,感觉上有点脱离代码规范了,优点也很明显,当你必须写回调函数的时候,逻辑很简单。)
<script>
export default {
name: "form-input"
, inject: ['formGroup']
, created: function () {
//给formGroup增加一个事件回调,此处不符合VUE数据单向数据流的设计要求,但是满足普通JS语法
let currentWidget = this;
for (let i = 0; i < currentWidget.formGroup.length; i++) {
if (currentWidget.formGroup[i].name === this.name) {
currentWidget.formGroup[i].isValid = function () {
return currentWidget.checkFormInputValidity();
}
}
}
}, methods: {
/**
* 比较当前值是否有效
*/
checkFormInputValidity: function (value) {
}
}
}
<script>