需求是根据JSON文件生成表单,包含配置和自动model属性以及表单验证,数据回显。
目录
动态表单数据示例:
表单设置JSON示例:
表单输入JSON示例:
表单按钮JSON示例:
抛出数据示例:
动态表单示例:
HTML模板部分:
PROPS部分:
表单验证器:
事件部分:
为了数据回显
props新增defaultValue:
computed增加监听:
data中申明
组件引用示例:
HTML 部分:(导入就不说了)
效果如下:
动态表单数据示例:
(page/home/index.js)
表单设置JSON示例:
/**
* 搜索表单设置
* @rules: 是否验证 {Boolean}
* @inline: 是否内联 {Boolean}
* @width: label宽度 {String}
* @align: label对齐方式 {String}
*/
const searchFormSetting = {
rules: false,
inline: true,
ref: 'searchForm',
width: '40px',
align: 'left'
}
表单输入JSON示例:
/**
* 搜索表单
* @type: 输入框的类型
* @label: 输入框的label
* @module: 输入框的v-module属性,不写会默认咦中文首字母拼音作为改属性
* 注:select需要配合options使用
*/
const searchFormGroup = [
{ label: '早餐', type: 'input', module: 'zaofan' },
{ label: '日期', type: 'date' },
{ label: '地点', type: 'select', options: addressOptions }
]
表单按钮JSON示例:
/**
* 搜索表单按钮事件
* @name: 按钮名称
* @event: 按钮事件名(子组件直接@eventName=handleCustomizeEvent)
* @primary:按钮类型(按钮的颜色)
* @icon:按钮的小图标
*/
const searchFormButton = [
{ name: '查询', event: 'search', type: 'primary', icon: 'el-icon-search' },
{ name: '重置', event: 'reset', icon: 'el-icon-refresh-left' },
{ name: '一键导出', event: 'export', icon: 'el-icon-download' }
]
抛出数据示例:
export { searchFormSetting, searchFormGroup, searchFormButton}
动态表单示例:
(components/autoForm/index.vue)
HTML模板部分:
<template>
<el-form ref="autoForm" :model="autoForm" :rules="autoRules" :label-width="setting.width" :inline="setting.inline" :label-position="setting.align" :id="setting.inline">
<el-form-item v-for="(item, key) in form" :key="key" :label="item.label" :prop="chineseToPinYin(item.label)">
<!--input-->
<template v-if="item.type === 'input'">
<template>
<el-input v-model="autoForm[item.module || chineseToPinYin(item.label)]" :placeholder="'请输入'+item.label" @input="handleRefresh"/>
</template>
</template>
<!--select-->
<template v-if="item.type === 'select'">
<el-select filterable v-model="autoForm[item.module || chineseToPinYin(item.label)]" :placeholder="'请选择'+item.label" @change="handleRefresh">
<el-option v-for="(item_, key_) in item.options" :key="key+'_'+key_" :label="item_.label" :value="item_.value"></el-option>
</el-select>
</template>
<!--date-->
<template v-if="item.type === 'date'">
<el-date-picker type="date" value-format="yyyy-MM-dd" format="yyyy-MM-dd" :placeholder="'请选择'+item.label" v-model="autoForm[chineseToPinYin(item.label)]" @change="handleRefresh"></el-date-picker>
</template>
<!--radio-->
<template v-if="item.type === 'radio'">
<el-radio-group v-model="autoForm[item.module || chineseToPinYin(item.label)]" @change="handleRefresh">
<el-radio v-for="(item_, key_) in item.options" :key="key_" :label="item_.label" :value="item_.value"></el-radio>
</el-radio-group>
</template>
<!--textarea-->
<template v-if="item.type === 'textarea'">
<el-input type="textarea" v-model="autoForm[item.module || chineseToPinYin(item.label)]"/>
</template>
</el-form-item>
<!--BUTTON--GROUP-->
<el-form-item v-if="button">
<el-button v-for="(item, key) in button" :key="'btn-'+key" :class="item.float" :icon="item.icon" :type="item.type" @click="handleButton(item.event, 'autoForm')">{{ item.name }}</el-button>
</el-form-item>
</el-form>
</template>
PROPS部分:
props: {
setting: {
type: Object,
default: () => ({
ref: 'form',
width: '80px',
align: 'left'
})
},
button: {
type: Array,
default: () => [
{ name: '查询', event: 'search', type: 'primary', icon: 'el-icon-search' },
{ name: '重置', event: 'reset', type: 'success', icon: 'el-icon-refresh-left' }
]
},
form: {
type: Array,
default: () => [
{ label: '类型', type: 'select' },
{ label: '分数', type: 'input' },
{ label: '时间', type: 'date' }
]
}
}
表单验证器:
this.form.forEach(item => {
this.autoRules[chineseToPinYin(item.label)] = verify(item)
})
function verify (item) {
let rules = []
if (item.required && item.type === 'input') {
rules = [{ required: true, message: `请输入${item.label}`, trigger: ['blur', 'change'] }]
} else if (item.required && item.type === 'select') {
rules = [{ required: true, message: `请选择${item.label}`, trigger: ['blur', 'change'] }]
} else if (item.required && item.type === 'textarea') {
rules = [{ required: true, message: `请输入${item.label}`, trigger: ['blur', 'change'] }]
} else if (item.required && item.type === 'date') {
rules = [{ type: 'date', required: true, message: `请选择${item.label}`, trigger: ['blur', 'change'] }]
} else if (item.required && item.type === 'radio') {
rules = [{ required: true, message: `请选择${item.label}`, trigger: ['blur', 'change'] }]
}
return rules
}
事件部分:
handleButton (event, autoForm) {
if (event === 'reset' || event === 'cancel') {
this.autoForms = {}
} else {
this.$refs[autoForm].validate((valid) => {
if (valid) {
this.$emit(event, this.autoForms, this.setting.ref)
} else {
this.$message({
type: 'warning',
message: '请检查您的输入'
})
}
})
}
},
handleRefresh () {
this.$forceUpdate()
}
为了数据回显
props新增defaultValue:
defaultForm: {
type: Object,
default: () => ({})
}
computed增加监听:
autoForm () {
return this.autoForms
}
data中申明
(注意区分autoForms和autoForm)
return {
autoForms: this.defaultForm
}
组件引用示例:
(page/home/index.vue)
HTML 部分:(导入就不说了)
<auto-form :setting="searchFormSetting" :form="searchFormGroup" :button="searchFormButton" :default-form="searchForm" @search="handleClickSearchFormSearch" @export="handleClickSearchFormExport"/>