介绍
mc-form
,一个表单通用组件,目的是通过一份配置文件生成一个表单,减少重复性的工作。demo。
安装
npm install mc-form -S
使用
import Vue from 'vue';
import McForm from 'mc-form';
import 'mc-form/dist/assets/index.css';
Vue.component(McForm.name, McForm);
组件属性: config
mc-form
的配置文件,根据该配置生成表单
{
symbol: false,
gutter: 10,
labelWidth: '80px',
state: {},
properties: []
}
表单项配置: config.properties
config.properties
为数组,里面包含了各种表单项的相关配置对象。通用字段如下:
{
type: 'text|number|password|select|checkbox|radio|time|year|month|date|dates|week|datetime|datetimerange|daterange|monthrange|selector|editor|inputrange|upload|tree|component',
field: 'field',
label: 'label',
value: 'value',
ui: {
column: 24,
size: 'mini',
wrap: false,
occupation: true,
hidden: false,
disabled: false,
readonly: false,
clearable: false,
placeholder: '',
labelWidth: ''
},
linkeds: [
{
path: 'field',
value: 'dx:{{ [] }}',
refresh: true
}
],
rules: [
{ required: true, message: '必填', trigger: 'change'}
]
}
{
type: 'text|number|password',
field: 'field',
value: null,
label: '文本框'
input: {
}
}
2. inputnumber demo
{
type: 'inputnumber',
field: 'field',
value: null,
label: '数量'
inputnumber: {
}
}
{
type: 'radio',
field: 'field',
value: null,
label: '单选框',
options: {
data: [ { label: '是', value: 1 } ] || 'state.DICT.dict.vipLevels',
label: 'label',
value: 'value',
ajax: {
request: (data, params) => Promise.reolve([]),
url: '/url',
params: {
id: 'dx:{{ $state.id }}'
},
data: {
name: 'dx:{{ $state.name }}'
},
method: 'post',
beforeSend: 'dx:{{ !!$state.parentId }}',
path: 'data.content'
},
include: [],
exclude: []
},
radio: {
border: false,
textColor: '#fff',
fill: '#409EFF'
}
}
{
type: 'checkbox',
field: 'field',
value: null,
label: '多选框',
options: {
data: [ { label: '是', value: 1 } ] || 'state.DICT.dict.vipLevels',
label: 'label',
value: 'value',
ajax: {
request: (data, params) => Promise.reolve([]),
url: '/url',
params: {
id: 'dx:{{ $state.id }}'
},
data: {
name: 'dx:{{ $state.name }}'
},
method: 'post',
beforeSend: 'dx:{{ !!$state.parentId }}',
path: 'data.content'
},
include: [],
exclude: [],
checkAll: true
},
}
{
type: 'select',
field: 'field',
value: null,
label: '选择框',
options: {
data: [ { label: '是', value: 1 } ] || 'state.DICT.dict.vipLevels',
label: 'label',
value: 'value',
ajax: {
remote: 'name',
request: (data, params) => Promise.reolve([]),
url: '/url',
params: {
id: 'dx:{{ $state.id }}'
},
data: {
name: 'dx:{{ $state.name }}'
},
method: 'post',
beforeSend: 'dx:{{ !!$state.parentId }}',
path: 'data.content'
},
include: [],
exclude: [],
additional: {
[label]: 'label',
[value]: 'value'
}
},
select: {
}
}
6. 日期时间选择器 demo
{
type: 'time|year|month|date|dates|week|datetime|datetimerange|daterange|monthrange',
field: 'field',
value: null,
label: '日期选择器',
picker: {
}
}
该组件是为了类似于点击按钮,出现弹窗后选择
的类似需求,需要配合setState
和selector.event
使用。界面形式为左边el-tag
,右边el-button
{
type: 'selector',
field: 'field',
value: null,
label: '日期选择器',
selector: {
label: 'label',
type: 'primary',
text: '选择',
size: 'medium',
event: 'click',
closable: true,
}
}
需要额外安装mc-form-editor组件
{
type: 'editor',
field: 'field',
value: null,
label: '富文本',
editor:{
menus: [
'head',
'bold',
'fontSize',
'fontName',
'italic',
'underline',
'strikeThrough',
'foreColor',
'backColor',
'list',
'justify',
'image'
],
colors: [
'#000000',
'#eeece0',
'#1c487f',
'#4d80bf',
'#c24f4a',
'#8baa4a',
'#7b5ba1',
'#46acc8',
'#f9963b',
'#ffffff'
],
zIndex: 9,
path: 'content',
data: {}
action: null,
request: (formData) => Promise.reolve({}),
uploadFileName: 'file',
uploadImgShowBase64: false,
uploadImgMaxSize: 1 * 1024 * 1024,
onSuccess: _ => ({ success: true })
}
}
9. 文本框范围 demo
{
type: 'inputrange',
field: 'field',
value: null,
label: '文本框范围',
inputrange: {
startPlaceholder: '',
endPlaceholder: '',
rangeSeparator: '-',
type: 'number'
}
}
10. 文件上传 demo
{
type: 'upload',
field: 'field',
value: null,
label: '文件上传',
upload: {
accept: 'image/jpeg,image/jpg,image/png',
action: '',
headers: {},
multiple: false,
name: 'file',
limit: 0,
tip: '',
listType: 'picture-card',
limitSize: 1,
beforeUpload: blob => Promise.reject(),
onSuccess: res => ({ success: res.code === 200, message: res.chnDesc, uri: res.content }),
}
}
11. 树
抱歉,尚未实现异步加载
{
type: 'tree',
field: 'field',
value: null,
label: '树',
tree: {
data: [] || 'state.USER.user.permissionTree',
emptyText: '暂无数据',
nodeKey: 'id',
props: {
label: 'label',
children: 'children'
},
highlightCurrent: false,
defaultExpandAll: false,
expandOnClickNode: true,
checkOnClickNode: false,
autoExpandParent: true,
checkStrictly: false,
accordion: false,
leafOnly: false,
includeHalfChecked: false,
deep: false
}
}
12. 纯文本
纯文本,可用于写个表头或者描述性文本
{
type: 'plaintext',
plaintext: {
align: 'center',
text: '',
clsName: ''
}
}
13. 自定义组件 demo
众所周知,产品的需求是相当骚的,为了实现某些骚操作,开放自定义组件的功能供开发者使用。
{
type: 'component',
component: Component
}
使用自定义组件可接受以下 props: ['state', 'gutter']
。同时,由于自组件不能修改父组件的数据,需要额外$emit,不能舒舒服服的用v-model
,请自行衡量。
this.$emit('update:object', this.state, 'name', '刘伟健');
this.$emit('update:object', this.state, { name: '刘伟健' });
this.$emit('update:array', this.state.users, 'push', { name: null, sex: null });
修改默认配置
由于默认配置不太适合于其他项目,所以提供一个可修改默认配置的方法。PS:请在mc-form
注册前设置。
import instance from '@http/instance';
import McForm, { setDefaultConfigs } from 'mc-form';
export default function install(Vue) {
Vue.component(McForm.name, McForm);
setDefaultConfigs({
request: instance,
upload: {
onSuccess: res => ({ success: false, message: 'error' })
};
});
}
组件实例方法
{
getState(field) {},
validate() {},
clear() {},
setState(field, value) {},
replace(state) {},
setEditable(field, prop, expr) {},
setOptions(field, prop, options) {},
reset() {}
}
组件事件
组件事件只针对内置组件做通知,自定义组件不会触发。回调参数为一个对象: { field, value }
,value视element-ui的相关组件的相关事件的回调参数而定。
- change: 值改变时触发,相当于
input
,历史原因,保留命名 - native-change: 相当于
change
- blur: 失去焦点触发
- focus: 获取焦点触发
<mc-form @change="handleChange"></mc-form>
dx表达式的存在是为了实现数据关联的效果。例如,当某字段为空时不允许编辑 disabled: 'dx:{{ !$state.field }}'
,具有以下特点:
- 格式如:'dx:{{ expression }}'
- 特殊字段
$state
代表表单(el-form
)的model
对象 - 不允许赋值的存在,比如 'dx{{ $state.name = 1 }}'是不合法的
关联字段的存在是为了设置关联的字段值,和刷新相关的选项。
关于特殊符号拼接的字段 demo
为了更方便地获取和设置mc-form
的state
,可以使用symbol: true
开启以下特殊符号在字段中的特殊作用
-
: 范围字段设置。例如: state['a-b'] = [ state.a, state.b ],主要应用于range相关的组件>
: 路径字段设置。例如: state['a>b'] = state.a.b@
: 设置关联字段为数组。例如字段 tagIds@tagNames, state = {tagIds: [1,2,3], tagNames: ['刘', '伟', '健']},会被设置为 state['tagIds@tagNames'] = [{id: 1, name: '刘'}, {id: 2, name: '伟'}, {id: 3, name: '健'}]&
: 设置关联字段为对象。例如字段 tagId&tagName, state = {tagId: 1, tagName: '刘伟健'},会被设置为 state['tagId&tagName'] = { id: 1, name: '刘伟健' }
关于请求缓存
对于某些请求,例如获取省市区,我们希望能够缓存起来不做二次请求。考虑到mc-form
不能进行全局缓存,所以便不支持。但是开发者者可以在ajax.options.request
上做处理。以下为实现全局缓存的例子,仅供参考:
export function createCaches(fn, prop) {
let caches = {};
let cb = function _cache(params) {
let key = params[prop];
if (isEmptyValue(key)) {
return Promise.reject(new Error(`params.${prop} is required`));
}
if (!caches[key]) {
caches[key] = fn.call(this, params).catch(e => {
delete caches[key];
return Promise.reject(e);
});
}
return caches[key];
};
cb.clear = function(key) {
isEmptyValue(key) ? (caches = {}) : (delete caches[key]);
};
return cb;
}
const requestRegions = createCaches(data => $http.post('/area', data.parentId === 'TOP' ? {} : data), 'parentId');
const config = {
properties: [
{
label: '省市区',
type: 'select',
field: 'provinceId',
value: null,
ui: {
column: 8
},
options: {
ajax: {
request: requestRegions,
data: {
parentId: 'TOP'
}
},
label: 'name',
value: 'id'
},
linkeds: [
{
path: 'cityId',
value: null,
refresh: true
}
]
},
{
label: '',
type: 'select',
field: 'cityId',
value: null,
ui: {
column: 4
},
options: {
ajax: {
request: requestRegions,
data: {
parentId: 'dx:{{ $state.provinceId }}'
},
beforeSend: 'dx:{{ !!$state.provinceId }}'
},
label: 'name',
value: 'id'
},
linkeds: [
{
path: 'countyId',
value: null,
refresh: true
}
]
},
{
label: '',
type: 'select',
field: 'countyId',
value: null,
ui: {
column: 4
},
options: {
ajax: {
request: requestRegions,
data: {
parentId: 'dx:{{ $state.cityId }}'
},
beforeSend: 'dx:{{ !!$state.cityId }}'
},
label: 'name',
value: 'id'
}
}
]
}