封装 el-form
2020-10-23 本文已影响0人
McDu
<el-form :inline="true" :model="form">
<el-form-item label="目的地">
<el-input v-model="form.arrive" placeholder="目的地"></el-input>
</el-form-item>
<el-form-item label="产品名称">
<el-input v-model="form.enProductId" placeholder="产品名称"></el-input>
</el-form-item>
<el-form-item label="产品ID">
<el-input v-model="form.productTitle" placeholder="产品ID"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="queryList(1)">搜索</el-button>
</el-form-item>
</el-form>
- 配置字段:根据 type 字段配置,比如 text、input、number、select、textarea、date、button 等。
export const formField = [
{
label: '纯文本:',
value: 'text',
type: 'text'
},
{
label: '普通输入框:',
value: 'input_normal_test',
type: 'input',
placeholder: '不能为空',
rules: R.inputNotEmpty({label: '订单号'})
},
{
label: '字数限制:',
value: 'input_numlimit_test',
type: 'input',
placeholder: '最多 5 个字',
rules: [R.inputNotEmpty({label: '产品名称'}), getRule({rule: 'max', range: [5]})]
},
{
label: '选择框:',
value: 'select_test',
type: 'select',
options: selectOption
},
{
type: 'slot',
label: 'Slot 测试:',
value: 'hahaha'
},
{
label: '日期时间:',
value: 'date_test',
type: 'date',
dateType: 'datetime',
valueFormat: 'yyyy-MM-dd hh:mm:ss',
rules: R.chooseNotEmpty(),
pickerOptions: {
disabledDate(time) {
return time.getTime() < Date.now() - 24 * 60 * 60 * 1000;
}
}
},
{
label: '数字:',
value: 'number_test',
type: 'number',
placeholder: '请输入数字',
suffix: '小时',
rules: [R.inputNotEmpty({label: '数字'}), R.intNumber()]
},
{
label: '文本域:',
value: 'textarea_test',
type: 'textarea',
rules: R.inputNotEmpty()
},
{
text: '提交',
type: 'button',
event: 'submit'
},
{
text: '重置',
type: 'button',
event: 'reset',
styleType: 'defalut'
}
];
- 表单项校验。内置 inputNotEmpty、chooseNotEmpty、intNumber,可以使用 getRule 方法根据自定义规则校验,比如 最大值、最小值、整数、中文、字符串等。
// {0} 代表表单字段名, {1} {2} 代表分别代表验证条件 range[0] range[1]
const errors = {
notEmpty: '请输入{0}',
max: '{0}最多为 {1} 个字符',
min: '{0}最小为 {1} 个字符',
fixedNum: '请输入{1}个字符',
length: '{0}的长度在 {1} 到 {2} 个字符',
number: '{0}必须是数字',
intNum: '{0}必须是整数',
numRange: '请输入{1}~{2}之间的数字',
floatNum: '{0}必须是整数或最多两位小数',
string: '{0}必须是字母或者数字',
noChinese: '{0}不能为中文',
chinese: '{0}必须为中文'
};
const methods = {
notEmpty: v => v || v === 0,
min: (v, arr) => v.length >= arr[0],
max: (v, arr) => v.length <= arr[0],
fixedNum: (v, arr) => v.length === arr[0],
length: (v, arr) => arr[0] <= v + '' && v + '' <= arr[1],
number: v => /^\d+(\.\d+)?$/.test(v),
intNum: v => /^\d*$/.test(v),
numRange: (v, arr) => {
if(!v) {
return true;
}
if (!methods.number(v)) {
return false;
}
if(v < arr[0] || v > arr[1]) {
return false;
}
return true;
},
floatNum: v => /^\d+(\.\d{1,2})?$/.test(v),
string: v => /^[a-zA-Z0-9]*$/.test(v),
chinese: v => /[\u4e00-\u9fa5]/.test(v),
noChinese: v => !/[\u4e00-\u9fa5]/.test(v)
};
/**
* @description: 生成 rules
* @param {Object}
* * @param {String} rule 要使用的规则名称
* * @param {Array} range 规则数组
* * @param {String} trigger 触发条件
* * @param {String} label 表单字段名
* * @param {Boolean} required 是否必填
* * @return {Object} {required, validator, trigger, message?, type?}
*/
export const getRule = ({rule, range, trigger = 'blur', label = '', required = true, errMsg = ''}) => {
let validator,
cRule = methods[rule],
cError = errMsg || errors[rule];
const result = {
required,
trigger
};
if (cRule) {
validator = (rule, val, cb) => {
// 校验通过:
// 1. 必填,val 存在 && 符合 rule
// 2. 非必填,val 存在 && 符合 rule
const passRule = cRule(val, range);
let valid = passRule;
if(required) {
if(val && passRule) {
valid = true;
} else {
valid = false;
}
} else {
if(!val) {
valid = true;
}
}
if(valid) {
cb();
} else {
range && range.forEach((v, k) => {
cError = cError.replace(`{${k + 1}}`, v);
});
cError = cError.replace('{0}', label);
cb(new Error(cError));
}
};
result.validator = validator;
} else {
result.message = trigger === 'change' ? '请选择' : '请输入';
}
return result;
};
export const R = {
inputNotEmpty(param) {
return getRule({
rule: 'notEmpty',
...param
});
},
chooseNotEmpty(param) {
return getRule({
trigger: 'change',
...param
});
},
// todo: trigger has problem
arrayNotEmpty(param) {
return getRule({
trigger: 'change',
type: 'array',
...param
});
},
intNumber(param) {
return getRule({
rule: 'number',
...param
});
}
};
- 表单项的展示隐藏控制,通过 hidden 属性控制,分角色,管理员和供应商。
// 获取字段列表
getConfigList() {
return this.fieldList.filter(v => !v.hidden);
},
{
label: '套餐ID:',
value: 'packageId',
type: 'input',
hidden: !isAdmin
},
- $attr 支持原有属性的传递:可以在 qform 组件传递任意非 style、class 的原生 el-form 属性。比如 inline、lable-width。
<q-form
:ref-obj.sync="form.ref"
:data="form.data"
:field-list="form.fields"
@search="queryList" // search 事件
inline // el-form 属性
></q-form>
- 事件传递:内置 submit、search、reset 事件,默认 handle-event。
// QForm.vue
<!-- 提交、重置 -->
<el-button
v-if="item.type === 'button'"
:type="item.styleType || 'primary'"
@click="handleEvent(item.event)"
>
{{ item.text }}
</el-button>
// 绑定的相关事件
handleEvent(event, data) {
switch (event) {
case "submit":
case "search":
case "reset":
this.$emit(event, data);
this.$emit("handle-event", event, data);
break;
default:
this.$emit("handle-event", event, data);
}
},
// config.js
export const taocanFields = [
{
text: '提交',
type: 'button',
event: 'submit'
},
{
text: '重置',
type: 'button',
event: 'reset',
styleType: 'defalut'
}
]
// 使用
<q-form
:ref-obj.sync="formInfo.ref"
:data="formInfo.data"
:field-list="formInfo.fieldList"
:label-width="formInfo.labelWidth"
@handle-event="onFormInfoEvent"
className="form-wrap"
/>
// 表单提交
onFormInfoEvent(event) {
switch (event) {
case "submit":
this.onSubmit();
break;
case "reset":
this.onReset();
break;
}
},