这里不考虑ref的使用,通过ref的方式,可以解决大部分问题,但是就和写html一样,不到万不得已你不会使用id,
而且极端场合下,如何给组件设置id,本身就是一个难题。
业务场景:
我们设计一个表单组件,需要用户填写年龄,因此有个输入框,我们使用 v-model 绑定年龄字段,
显然,年龄不能超过200,因此组件还必须给出校验位,当年龄超过200,校验位就置成false,
因为校验位是在组件内部凭空产生的,父组件如何获取校验位就成了一个难题。
(表单不会只有1个输入框,因此很难设置 ref )
方案1:实现v-model
简单的实现方案,就是实现自定义组件的 v-model 功能,缺点就是 v-model 只能绑定一个值。
(当然,这个方案不适合前面提到的案例,你可以考虑绑定一个对象,而不是一个值,因此列为一种解决方案。)
方案2:传递对象
props使用Object类型,父组件将一整个对象传递给子控件,父子组件都可以对参数进行修改、取值。
以下面代码为例,<data-table>组件的参数是一个Object类型,父子组件只要约定好参数中的内容即可。
这或许是最优解了,写法上不会太过另类,而且,Vue也不会阻止子组件修改Object的字段值。
感觉上,这种做法似乎有些脱离了Vue设计初衷,Vue不会阻止子组件修改Object参数的内容,
同时,Vue 不会主动侦听 Object 字段的变化,最直接的问题,就是页面数据可能不发生联动了,
不过即便不联动,使用watch、computed也能解决问题,办法总比困难多,主要也看编程如何取舍了。
<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。
其他人看不到父子组件之间传递参数,但是子组件确确实实获得了父组件的参数,
如果也希望设计这样的组件,这时候就要用到 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>