雷同代码,就要拿出来做成共用函数
属性
表单的子控件,有很多相同的属性,如果每个组件都写一遍,就太麻烦了,而且也不便于实现统一的维护和增改。
那么怎么办呢?我们可以建立一个 js文件,在里面设置组件的共同的属性。
// control-props.js
/**
* 基础控件的共用属性
*/
export const baseProps = {
controlId: { // 101 控件ID,必填
type: Number,
default: () => Math.floor((Math.random()*10000000)+1) // 避免必须设置ID的麻烦
},
colName: String, // 102 字段名称
controlType: Number, // 104 控件类型编号
size: { // 109 medium / small / mini 三选一,不必填
type: String,
default: 'mini',
validator: (value) => {
// 这个值必须匹配下列字符串中的一个
return ['medium', 'small', 'mini'].indexOf(value) !== -1
}
},
optionList: { // 选项
type: Array,
default: () => []
},
clearable: { // 统一设置,是否可清空,默认可以清空
type: Boolean,
default: true
},
validate_event: { // 统一设置,不必填,输入时是否触发表单的校验
type: Boolean,
default: true
},
show_word_limit: { // 统一设置,不必填,是否显示输入字数统计 text和area有效
type: Boolean,
default: true
}
}
其他属性用 $attrs 的方式自动传递。
内部成员和事件。
因为 element-plus 把 value 也封装成了 v-model 的形式,所以无法直接绑定组件的属性(modelValue),那么就需要做一个内部变量做中转,这个处理方式也是共用的,可以拿出来放在单独的 js 文件里面。
/**
* 表单子控件的管理类
* @param {*} props 组件的属性,获取modelValue和meta属性
* @param {*} context 上下文获取emit,提交数据
* @returns {*} value:绑定到组件的值
* @returns {*} mySubmit:向父组件提交的事件
*/
const controlItemManage = (props, context) => {
// 用于绑定控件的值。
const value = debounceRef(props, context)
// 向父组件提交事件
const mySubmit = (val) => {
// 修改 modelValue 属性
context.emit('update:modelValue', val)
// 提交 myChange 表单组件需要用,可以得到组件ID和字段名称,
// 用于区分是哪个组件触发的事件。
context.emit('my-change', val, props.controlId, props.colName)
}
return {
value,
mySubmit
}
}
组件里调用
首先引入两个 js 文件,然后就可以使用了。
import { defineComponent } from 'vue'
// 引入表单子控件的管理类
import controlItemManage from '/ctrlManage/control-item.js'
// 引入组件需要的属性
import { baseProps } from '/ctrlManage/control-props.js'
export default defineComponent({
name: 'el-form-item-text',
props: {
...baseProps, // 基础属性
modelValue: [String, Array, Number]
},
emits: ['update:modelValue', 'my-change'],
setup (props, context) {
return {
...controlItemManage(props, context) // value、mySubmit
}
}
})
...的解构方式还是非常好用的。
本来这里打算改成 script setup 的形式的,但是遇到了两个问题。
- 属性无法拿出去共用,到目前为止还没有找到方法。
- 解构方式不知道怎么改。
这样组件代码就简洁多了,而且也方便维护。
模板里面设置属性就好。
<el-input
v-model="value"
@clear="mySubmit"
:id="'c' + controlId"
:name="'c' + controlId"
:size="size"
:clearable="clearable"
:validate_event="validate_event"
:show-word-limit="show_word_limit"
>
</el-input>
像文本、密码这些简单的组件,js部分基本不用写代码了,模板里面只需要设置属性就好,非常简单好维护。