vue - 子级向父级传递参数

就和 html 一样,不到万不得已你不会使用 id,因此也不考虑 ref 的使用。


业务场景

设计一个表单组件,需要用户填写年龄,因此有个输入框,我们使用 v-model 绑定年龄字段,
显然,年龄不能超过 200,因此组件还必须给出校验位,当年龄超过 200,校验位就置成false,
因为校验位是在组件内部凭空产生的,父组件如何获取校验位就成了一个难题。

解决思路

总得来说,就是改变参数类型,原先我们只想传递单个数值,如果传递一整个对象,或者一个回调函数,即可解决问题。

方案1:v-model

简单的实现方案,就是实现自定义组件的 v-model 功能,缺点就是 v-model 只能绑定一个值。

(虽说只能绑定一个值,但是这个值可以是一个对象,因此列为一种解决方案,最好的案例就是 el-form)

<el-form :model="numberValidateForm" ref="numberValidateForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="年龄" prop="age">
	<el-input v-model.number="numberValidateForm.age" autocomplete="off"></el-input>
</el-form-item>
</el-form>
<script>
export default {
	data() {
		return {
			numberValidateForm: {
				age: ''
			}
		};
	}
}
</script>

方案2:props

props 使用 Object 类型,万物皆对象,Object 意味着可以传递一切,绕过了所有限制。
以下面代码为例,参数是一个很复杂的对象,父子组件只要约定好参数中的内容即可。

<template xmlns="http://www.w3.org/1999/html">
    <data-table :table="table"></data-table>
</template>

<script>
    import DataTable from '@/components/widget/DataTable.vue'

    export default {
        components: {
            DataTable
        },
        data() {
            return {
                table: {
                    //分页配置
                    url: undefined
                    , page: 1
                    , limit: 10
                    , enabledSelection: true
                    , resultParser: undefined
                    , data: [{
                        date: '2016-05-02',
                        name: '王小虎',
                        address: '上海市普陀区金沙江路 1518 弄',
                        isDisabled: false,
                        select: 1,
                        image: 'http://www.baidu.com'
                    }]
                }
            }
        }
    }
</script>

方案3:provide

本质上与方案 2 完全一致,不过不用 props,而是使用 provide,也是将一整个对象传递给子控件。

两种做法,应用场景有些不同。

案例:

可以查看 element-ui 的 table 设计,table 和 column 一般会同时使用,
我们只把数据传递给了 table 组件,但是 column 明显也获取了我们的数据,
我们并没有看到 table 将数据传递给 column。

(el-form 与 el-form-item 的关系亦是如此)

其他人看不到父子组件之间传递参数,但是子组件确确实实获得了父组件的参数,
如果也希望设计这样的组件,这时候就要用到 provide,provide 能起到暗度陈仓的效果,悄悄地就把参数传给了子组件。

父级控件

通过 provide,将自己的参数传递到子级控件。

<script>
    import FormInput from './FormInput.vue'

    export default {
        name: "fast-form"
        , provide() {
            return {
                formGroup: this.formGroup
            };
        }
    }      
<script>
子级控件

通过 inject 接收父级传递的参数。

<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>

posted on 2021-12-21 16:34  疯狂的妞妞  阅读(1018)  评论(0编辑  收藏  举报

导航