表单的自定义子控件
表单封装之后就会遇到一个古老的问题 —— 需要放进去一个新类型的子控件怎么办?
表单控件又不可能把所有类型的框架都封装进去,这在以前都是很头痛的问题,如果是需要修改封装好的代码才可以实现的话,那就太郁闷了。
但是现在在Vue里面,至少有两种解决方案,还都挺优雅的。
用插槽设置自定义组件
Vue的组件有插槽这个功能,一开始还没想起来,这的多谢好友“@我滴神”的提醒,才想起来可以用插槽。好吧其实是我以前还不会用插槽。。。
研究了一下Vue官网,又结合 el-input 设置的插槽理解了一下,发现还不难,于是给表单控件设置了这样的插槽。
<el-form :model="formModel" ref="formControl" // 官网把这两个属性设置成一样的,结果被坑了,,, :rules="rules" :inline="false" class="demo-form-inline" label-suffix=":" label-width="130px" size="mini" > <el-row> <!--不循环row,直接循环col,放不下会自动往下换行。--> <el-col v-for="(ctrId, index) in formColSort" :key="'form_'+index" :span="formColSpan[ctrId]" > <el-form-item :label="getCtrMeta(ctrId).label" :prop="getCtrMeta(ctrId).colName" > <!--判断要不要加载插槽--> <template v-if="getCtrMeta(ctrId).controlType === 1"> <slot :name="ctrId">父组件没有设置插槽</slot> </template> <!--表单item组件,采用动态组件的方式--> <template v-else> <component :is="ctlList[getCtrMeta(ctrId).controlType]" v-model="formModel[getCtrMeta(ctrId).colName]" v-bind="getCtrMeta(ctrId)" @myChange="mySubmit"> </component> </template> </el-form-item> </el-col> </el-row> </el-form> 复制代码
在原先v-for循环的基础上,加上一个判断,根据meta的controlType 来判断,如果=== 1 好的,那么就是要用插槽,然后把控件ID设置给插槽的name属性,这样就可以按照控件ID来加载外部指定的插槽了。
外部使用方法
父组件首先要设置好插槽,这个就可以很随意了,插槽嘛就是可以各种各样的,我们先来个简单的。
<elForm v-model="model" v-model:partModel="partModel" :meta="meta"> <template v-slot:102=""> <h3>这是外面建立的子控件</h3> <el-input v-model="model.colName" placeholder="请输入内容"></el-input> </template> <template v-slot:104=""> <h3>这是外面建立的另一个子控件</h3> <input type="text"> </template> </elForm> 复制代码
用 template 设置好控件ID,这样可以设置多个插槽。
然后再设置一下表单的meta即可
// 设置使用插槽的表单子控件 meta.itemMeta[102].controlId = 102 meta.itemMeta[102].colName = '属性名称' meta.itemMeta[102].controlType = 1 复制代码
属性的具体内以后在介绍,总之,不用改表单控件的内部代码,就可以实现随意往里加新的子控件的需求了。
支持验证等功能吗?
测试了一下,支持各种功能,表单数据验证、排序、占位等都是支持的,和表单自带的子控件是一样的功能。 只是 v-model 需要外部设置一下。
这些还要感谢 Vue 和 UI库的强大。
$ref怎么处理?
element的官网例子里面,重置表单用的是Vue2的方式,正巧在Vue 官网看到了$ref的用法,于是改成了Vue3的方式实现重置表单的功能。
// Vue2 的方法 methods: { resetForm(formName) { this.$refs[formName].resetFields(); } } // Vue3的方法 // 获取 $ref const formControl = ref(null) // 设置给el-form 的ref属性 onMounted(() => { console.log('表单dom', formControl) }) const resetForm = () => { // 清空表单 formControl.value.resetFields() } 复制代码
这样表的控件就更完善了,另外,这不过了几天嘛,结果再看代码,居然看不懂了。。。