目的
el-form 表单配置化,后期可以利用后端进行配置表单
支持栅格布局
el-form 属性大部分都支持
公共配置可以统一处理,如trim、input宽度等
最基本的组件,利用这组件后期可以优化简单的新增编辑弹窗写法
【disable,hide,rules】是可以写方法的!相当于可以动态控制隐藏显示,禁用启用,和动态规则
row col formItem 都支持slotName
源码
export default {
props: {
model: {
type: Object,
default: () => { },
},
itemWidth: {
type: String,
default: '200px',
},
rowItems: {
type: Array,
default: () => [],
},
formItems: {
type: Array,
default: () => [],
},
},
data() {
return {
};
},
mounted() {
// 默认选中光标,设置ref=focus
this.generateModel();
this.focus();
// 重新覆盖方法
this.$nextTick(() => {
const entries = Object.entries(this.$refs.form);
for (const [key, value] of entries) {
if (['clearValidate', 'validate', 'validateField'].includes(key)) {
this[key] = value;
}
}
});
},
methods: {
resetFields() {
// 重置
this.$refs.form.resetFields();
},
// 处理v-modelv value 值
hanlderValue(prop) {
// 对数组返回类型的组件处理
if (Array.isArray(prop) && prop.length > 0) {
const _key = prop.join('|');
return this.model[_key];
}
// 处理|下划线的
return this.model[prop];
},
// 处理FormItem绑定值
hanlderFormItemProp(prop) {
// 时间范围选择组件处理
if (Array.isArray(prop) && prop.length > 0) {
// 处理时间范围选择的类型数组的
return prop.join('|');
}
return prop;
},
// 处理改变值
hanlderModel(prop, value) {
// 时间范围选择组件处理
if (prop && Array.isArray(prop)) {
if (Array.isArray(value)) {
// 数组对应值
prop.forEach((key, index) => {
this.$set(this.model, key, value && value.length > 0 ? value[index] : null);
});
} else if ([null, '', undefined].includes(value)) {
// 数组有清除按钮时,数组一起清理
prop.forEach((key) => {
this.$set(this.model, key, undefined);
});
}
} else {
this.$set(this.model, prop, value);
}
},
// 默认生成字段,减少重复赋值繁琐工作
generateModel() {
let _formItems = [...this.formItems];
if (this.rowItems.length) {
_formItems = this.rowItems.reduce((arr, item) => {
if (item.cols && item.cols.length) {
item.cols.forEach((list) => {
if (list.formItem) {
arr.push({
...list.formItem,
});
}
});
}
return arr;
}, []);
}
const obj = _formItems.reduce((obj, item) => {
const { prop } = item;
if (prop && Array.isArray(prop)) {
obj[prop.join('|')] = undefined;
prop.forEach((key) => {
obj[key] = undefined;
});
} else {
obj[item.prop] = undefined;
}
return obj;
}, {});
const arr = Object.keys(obj).filter((k) => k.includes('|'));
const ll = Object.keys(obj).filter((k) => !k.includes('|'));
arr.forEach((key) => {
Object.defineProperty(this.model, key, {
get() {
// 每一个都是就返回[],el-date 会报错
if (key.split('|').map((k) => this[k]).every((v) => [undefined, null].includes(v))) {
return [];
}
return key.split('|').map((k) => this[k]);
},
set(value) {
if (value && value.length === key.split('|').length) {
key.split('|').forEach((k, index) => {
this[k] = value[index];
});
} else {
key.split('|').forEach((k) => {
this[k] = undefined;
});
}
},
configurable: true,
});
});
ll.forEach((key) => {
if (this.model[key]) {
this.$set(this.model, key, this.model[key]);
} else {
this.$set(this.model, key, undefined);
}
});
},
focus() {
this.$nextTick(() => {
if (this.$refs.focus) {
setTimeout(() => {
this.$refs.focus.focus();
}, 100);
}
});
},
},
render(createElement) {
// 父级slots
// form-item label slot
const slotLabel = (slotName) =>
createElement(
'template',
{
slot: 'label',
},
this.$slots[slotName],
);
// formItem 组件
const formItem = (item) => {
if (item) {
return createElement(
'el-form-item',
{
props: {
...item,
rules: typeof item.rules === 'function' ? item.rules() : item.rules || null,
prop: this.hanlderFormItemProp(item.prop),
},
scopedSlots: {
error: (prop) =>
this.$scopedSlots[item.slotErrorName] && this.$scopedSlots[item.slotErrorName](prop),
},
},
[
// 加入label插槽
item.slotLabelName ? slotLabel(item.slotLabelName) : '',
// 有插槽优先
item.slotName
? this.$scopedSlots[item.slotName] && this.$scopedSlots[item.slotName](this.model)
: createElement(item.type || 'el-input', {
//
ref: item.ref,
attrs: {
disabled: typeof item.disabled === 'function' ? item.disabled() : item.disabled || false,
...item.props,
},
props: {
clearable: true,
disabled: typeof item.disabled === 'function' ? item.disabled() : item.disabled || false,
...item.props,
value: this.hanlderValue(item.prop),
},
// 加样式
style: {
width: this.itemWidth,
...(item.style || (item.props && item.props.style)),
},
class: item.class || (item.props && item.props.class),
on: {
...item.on,
change: (value) => {
// 重写change方法
if (item.on && item.on.change) {
item.on.change(value);
}
this.hanlderModel(item.prop, value);
},
// el-input 场景
input: (value) => {
// 重写input方法
if (item.on && item.on.input) {
item.on.input(value);
}
this.hanlderModel(item.prop, value);
},
},
}),
],
);
}
return '';
};
// col 组件
const col = (item) => {
if (item) {
return createElement(
'el-col',
{
props: {
...item,
},
},
item.slotName ? [this.$slots[item.slotName]] : [formItem(item.formItem)],
);
}
return '';
};
// row组件
const row = (item) => {
if (item) {
return createElement(
'el-row',
{
props: {
...item,
},
},
item.slotName ? [this.$slots[item.slotName]] : item.cols.filter((col) => (typeof col.hide === 'function' ? !col.hide() : !col.hide)).map((list) => col(list)),
);
}
return '';
};
return createElement(
'el-form',
{
ref: 'form',
props: {
...this.$attrs,
model: this.model,
},
nativeOn: {
// https://github.com/ElemeFE/element/issues/3625
// 多个表单选项, 输入回车后并不会自动submit, 然而出现单个 input组件的时候, 聚焦input后按回车就会触发自动提交
submit(event) {
event.preventDefault();
},
},
on: {
...this.$listeners,
},
},
// rowItems 优先
this.rowItems.length
? this.rowItems
.filter((list) => (typeof list.hide === 'function' ? !list.hide() : !list.hide))
.map((item) => row(item))
: this.formItems
.filter((list) => (typeof list.hide === 'function' ? !list.hide() : !list.hide))
.map((item) => formItem(item)),
);
},
};
关键文档,大部分复制el-form
Attributes
参数说明类型可选值默认值model表单数据对象object——rules表单验证规则object——inline行内表单模式boolean—falselabel-position表单域标签的位置,如果值为 left 或者 right 时,则需要设置 label-widthstringright/left/toprightlabel-width表单域标签的宽度,例如 '50px'。作为 Form 直接子元素的 form-item 会继承该值。支持 auto。string——label-suffix表单域标签的后缀string——hide-required-asterisk是否隐藏必填字段的标签旁边的红色星号boolean—falseshow-message是否显示校验错误信息boolean—trueinline-message是否以行内形式展示校验信息boolean—falsestatus-icon是否在输入框中显示校验结果反馈图标boolean—falsevalidate-on-rule-change是否在 rules 属性改变后立即触发一次验证boolean—truesize用于控制该表单内组件的尺寸stringmedium / small / mini—disabled是否禁用该表单内的所有组件。若设置为 true,则表单内组件上的 disabled 属性不再生效boolean/function—false-分割线-------------formItems表单内组件arrayForm-Item—rowItems表单内组件支持layout布局,优先等级高于formItemsarrayRow Attributes—hide动态控制显隐booleanfalse—
Methods
方法名说明参数validate对整个表单进行校验的方法,参数为一个回调函数。该回调函数会在校验结束后被调用,并传入两个参数:是否校验成功和未通过校验的字段。若不传入回调函数,则会返回一个 promiseFunction(callback: Function(boolean, object))validateField对部分表单字段进行校验的方法Function(props: array | string, callback: Function(errorMessage: string))resetFields对整个表单进行重置,将所有字段值重置为初始值并移除校验结果—clearValidate移除表单项的校验结果。传入待移除的表单项的 prop 属性或者 prop 组成的数组,如不传则移除整个表单的校验结果Function(props: array | string)focus使 input 获取焦点-blur使 input 失去焦点,并隐藏下拉框-
Events
事件名称说明回调参数validate任一表单项被校验后触发被校验的表单项 prop 值,校验是否通过,错误消息(如果存在)
Slot
name说明label标签文本的内容
Scoped Slot
name说明error自定义表单校验信息的显示方式,参数为 { error }
Form-Item Attributes
参数说明类型可选值默认值prop表单域 model 字段,在使用 validate、resetFields 方法的情况下,该属性是必填的string传入 Form 组件的 model 中的字段—label标签文本string——label-width表单域标签的的宽度,例如 '50px'。支持 auto。string——required是否必填,如不设置,则会根据校验规则自动生成boolean—falserules表单验证规则object/funtion——error表单域验证错误信息, 设置该值会使表单验证状态变为error,并显示该错误信息string——show-message是否显示校验错误信息boolean—trueinline-message以行内形式展示校验信息boolean—falsesize用于控制该表单域下组件的尺寸stringmedium / small / mini-slotName插槽名字string——
Row Attributes
参数说明类型可选值默认值gutter栅格间隔number—0type布局模式,可选 flex,现代浏览器下有效string——justifyflex 布局下的水平排列方式stringstart/end/center/space-around/space-betweenstartalignflex 布局下的垂直排列方式stringtop/middle/bottom—tag自定义元素标签string*divslotName插槽名字string——
Col Attributes
参数说明类型可选值默认值span栅格占据的列数number—24offset栅格左侧的间隔格数number—0push栅格向右移动格数number—0pull栅格向左移动格数number—0xs {
if (action === 'confirm') {
await this.$refs.form.validate();
instance.confirmButtonLoading = true;
try {
// 请求接口编写的地方
instance.confirmButtonLoading = false;
done();
} catch (error) {
instance.confirmButtonLoading = false;
}
} else {
this.$refs.form.resetFields();
done();
}
},
});
} catch (error) {
console.error(error);
}
},
更新个版本23/6/1
|