Commit c68d92502303197f3dfed9bd157f9a66f61b88a8
1 parent
b14860fe
Exists in
master
and in
1 other branch
新增预览版表单组件
Showing
4 changed files
with
227 additions
and
38 deletions
Show diff stats
examples/views/layout/component.vue
| @@ -58,7 +58,7 @@ export default { | @@ -58,7 +58,7 @@ export default { | ||
| 58 | rangeIndex = index | 58 | rangeIndex = index |
| 59 | } | 59 | } |
| 60 | } | 60 | } |
| 61 | - this.currentAnchor = this.anchorList[rangeIndex].hash; | 61 | + this.currentAnchor = this.anchorList[rangeIndex] ? this.anchorList[rangeIndex].hash : {}; |
| 62 | }; | 62 | }; |
| 63 | // 初次加载时根据url hash跳转到指定锚点 | 63 | // 初次加载时根据url hash跳转到指定锚点 |
| 64 | if (this.$route.hash) { | 64 | if (this.$route.hash) { |
| @@ -0,0 +1,56 @@ | @@ -0,0 +1,56 @@ | ||
| 1 | +<template> | ||
| 2 | + <el-row :gutter="15" type="flex" style="flex-wrap: wrap;"> | ||
| 3 | + <template v-for="(item, index) in list"> | ||
| 4 | + <el-col v-if="item.group && item.list" :key="index" :span="item.group.span || 24"> | ||
| 5 | + <el-row :gutter="15" type="flex" style="flex-wrap: wrap;"> | ||
| 6 | + <el-col v-if="item.group.title" :span="24">{{ item.group.title || item.group }}</el-col> | ||
| 7 | + <form-render :list="item.list" :model="itemKey ? model[itemKey] || {} : model" @item-change="onItemChange" @form-item-change="onFormItemChange" :itemKey="item.group.key"></form-render> | ||
| 8 | + </el-row> | ||
| 9 | + </el-col> | ||
| 10 | + <el-col v-else :span="item.span || 12" :key="index"> | ||
| 11 | + <el-form-item :label="item.label" :label-width="item.labelWidth || '120px'" :prop="item.fullKey" :rules="item.rules"> | ||
| 12 | + <component :is="item.type" :value="itemValue({ item })" @input="v => handleInput({ value: v, item })"></component> | ||
| 13 | + </el-form-item> | ||
| 14 | + </el-col> | ||
| 15 | + </template> | ||
| 16 | + </el-row> | ||
| 17 | +</template> | ||
| 18 | + | ||
| 19 | +<script> | ||
| 20 | +export default { | ||
| 21 | + name: 'form-render', | ||
| 22 | + props: { | ||
| 23 | + list: Array, | ||
| 24 | + model: Object, | ||
| 25 | + itemKey: String, | ||
| 26 | + }, | ||
| 27 | + methods: { | ||
| 28 | + itemValue({ item }) { | ||
| 29 | + if (this.itemKey) { | ||
| 30 | + const groupItem = this.model[this.itemKey] || {}; | ||
| 31 | + return groupItem[item.key]; | ||
| 32 | + } else { | ||
| 33 | + return this.model[item.key]; | ||
| 34 | + } | ||
| 35 | + }, | ||
| 36 | + handleInput({ value, item }) { | ||
| 37 | + if (this.itemKey) { | ||
| 38 | + this.$emit('item-change', { [this.itemKey]: { ...this.model[this.itemKey], [item.key]: value } }); | ||
| 39 | + } else { | ||
| 40 | + this.$emit('item-change', { [item.key]: value }); | ||
| 41 | + } | ||
| 42 | + this.$emit('form-item-change', { [item.fullKey]: value }); | ||
| 43 | + }, | ||
| 44 | + onItemChange(value) { | ||
| 45 | + if (this.itemKey) { | ||
| 46 | + this.$emit('item-change', { [this.itemKey]: { ...this.model[this.itemKey], ...value } }); | ||
| 47 | + } else { | ||
| 48 | + this.$emit('item-change', value); | ||
| 49 | + } | ||
| 50 | + }, | ||
| 51 | + onFormItemChange(value) { | ||
| 52 | + this.$emit('form-item-change', value); | ||
| 53 | + } | ||
| 54 | + } | ||
| 55 | +} | ||
| 56 | +</script> | ||
| 0 | \ No newline at end of file | 57 | \ No newline at end of file |
| @@ -0,0 +1,102 @@ | @@ -0,0 +1,102 @@ | ||
| 1 | +<template> | ||
| 2 | + <el-form ref="form" size="small" :model="formModel"> | ||
| 3 | + {{ formModel }} | ||
| 4 | + <form-render :list="formList" :model="model" @item-change="onItemChange" @form-item-change="onFormItemChange"></form-render> | ||
| 5 | + </el-form> | ||
| 6 | +</template> | ||
| 7 | + | ||
| 8 | +<script> | ||
| 9 | +import FormRender from './form-render'; | ||
| 10 | + | ||
| 11 | +export default { | ||
| 12 | + components: { FormRender }, | ||
| 13 | + props: { | ||
| 14 | + value: Object, | ||
| 15 | + list: Array, | ||
| 16 | + }, | ||
| 17 | + data() { | ||
| 18 | + return { | ||
| 19 | + model: {}, | ||
| 20 | + formModel: {} | ||
| 21 | + } | ||
| 22 | + }, | ||
| 23 | + watch: { | ||
| 24 | + value(val) { | ||
| 25 | + const data = val || {}; | ||
| 26 | + this.model = data; | ||
| 27 | + let formModel = {}; | ||
| 28 | + const setFormModelValue = (list, parentKey) => { | ||
| 29 | + list.forEach(item => { | ||
| 30 | + item.fullKey = `${parentKey ? `${parentKey}-${item.key}` : item.key}`; | ||
| 31 | + if (item.value instanceof Object) { | ||
| 32 | + setFormModelValue(Object.keys(item.value).map(key => ({ key, value: item.value[key] })), item.fullKey); | ||
| 33 | + } else { | ||
| 34 | + if (item.fullKey) { | ||
| 35 | + formModel[item.fullKey] = item.value; | ||
| 36 | + } | ||
| 37 | + } | ||
| 38 | + }); | ||
| 39 | + }; | ||
| 40 | + setFormModelValue(Object.keys(data).map(key => ({ key, value: data[key] }))); | ||
| 41 | + // console.log(formModel); | ||
| 42 | + // Object.keys(formModel).forEach(key => { | ||
| 43 | + // this.formModel[key] = formModel[key]; | ||
| 44 | + // }); | ||
| 45 | + if (Object.keys(formModel).length > 0) { | ||
| 46 | + console.log(formModel); | ||
| 47 | + this.formModel = formModel; | ||
| 48 | + } | ||
| 49 | + }, | ||
| 50 | + }, | ||
| 51 | + computed: { | ||
| 52 | + formList() { | ||
| 53 | + const newList = [...new Set(this.list)] | ||
| 54 | + const generateFullKey = (list, parentKey) => { | ||
| 55 | + list.forEach(item => { | ||
| 56 | + if (item.group && item.list) { | ||
| 57 | + if (item.group.key) { | ||
| 58 | + item.fullKey = `${parentKey ? `${parentKey}-${item.group.key}` : item.group.key}`; | ||
| 59 | + // if (item.fullKey) { | ||
| 60 | + // this.formModel[item.fullKey] = ''; | ||
| 61 | + // } | ||
| 62 | + } else { | ||
| 63 | + item.fullKey = item.key; | ||
| 64 | + // if (item.fullKey) { | ||
| 65 | + // this.formModel[item.fullKey] = ''; | ||
| 66 | + // } | ||
| 67 | + } | ||
| 68 | + generateFullKey(item.list, item.fullKey); | ||
| 69 | + } else { | ||
| 70 | + item.fullKey = `${parentKey ? `${parentKey}-${item.key}` : item.key}`; | ||
| 71 | + // if (item.fullKey) { | ||
| 72 | + // this.formModel[item.fullKey] = ''; | ||
| 73 | + // } | ||
| 74 | + } | ||
| 75 | + }); | ||
| 76 | + }; | ||
| 77 | + generateFullKey(newList); | ||
| 78 | + return newList; | ||
| 79 | + } | ||
| 80 | + }, | ||
| 81 | + methods: { | ||
| 82 | + // 表单项值变化 | ||
| 83 | + onItemChange(item) { | ||
| 84 | + this.$emit('input', { ...this.model, ...item }); | ||
| 85 | + }, | ||
| 86 | + // 表单相校验值变化 | ||
| 87 | + onFormItemChange(item) { | ||
| 88 | + this.formModel = { ...this.formModel, ...item }; | ||
| 89 | + }, | ||
| 90 | + // 校验表单 | ||
| 91 | + validate() { | ||
| 92 | + this.$refs.form.validate(valid => { | ||
| 93 | + this.$emit("validate", valid); | ||
| 94 | + }); | ||
| 95 | + }, | ||
| 96 | + } | ||
| 97 | +} | ||
| 98 | +</script> | ||
| 99 | + | ||
| 100 | +<style> | ||
| 101 | + | ||
| 102 | +</style> | ||
| 0 | \ No newline at end of file | 103 | \ No newline at end of file |
examples/views/page/other.vue
| 1 | <template> | 1 | <template> |
| 2 | <div> | 2 | <div> |
| 3 | <p>这是一个非markdown页面</p> | 3 | <p>这是一个非markdown页面</p> |
| 4 | - <el-form size="small"> | ||
| 5 | - <el-row :gutter="15" type="flex" style="flex-wrap: wrap;"> | ||
| 6 | - <template v-for="(item, index) in option.list2"> | ||
| 7 | - <el-col v-if="item.group && item.list" :key="index" :span="item.group.span || 24"> | ||
| 8 | - <el-row :gutter="15" type="flex" style="flex-wrap: wrap;"> | ||
| 9 | - <el-col :span="24">{{ item.group.title || item.group }}</el-col> | ||
| 10 | - <el-col v-for="(comp, idx) in item.list" :key="idx" :span="comp.span || 12"> | ||
| 11 | - <el-form-item :label="comp.label" :label-width="comp.labelWidth || '120px'" :prop="comp.key" :rules="comp.rules"> | ||
| 12 | - <component :is="comp.type"></component> | ||
| 13 | - </el-form-item> | ||
| 14 | - </el-col> | ||
| 15 | - </el-row> | ||
| 16 | - </el-col> | ||
| 17 | - <el-col v-else :span="item.span || 12" :key="index"> | ||
| 18 | - <el-form-item :label="item.label" :label-width="item.labelWidth || '120px'" :prop="item.key" :rules="item.rules"> | ||
| 19 | - <component :is="item.type"></component> | ||
| 20 | - </el-form-item> | ||
| 21 | - </el-col> | ||
| 22 | - </template> | ||
| 23 | - </el-row> | ||
| 24 | - </el-form> | 4 | + <pre>{{ model }}</pre> |
| 5 | + <el-button size="mini" @click="handleGetValue">校验</el-button> | ||
| 6 | + <eg-form ref="form" v-model="model" :list="option.list" @validate="onValidate"></eg-form> | ||
| 25 | </div> | 7 | </div> |
| 26 | </template> | 8 | </template> |
| 27 | 9 | ||
| 28 | <script> | 10 | <script> |
| 11 | +import EgForm from './form'; | ||
| 12 | + | ||
| 29 | export default { | 13 | export default { |
| 30 | name: 'other', | 14 | name: 'other', |
| 15 | + components: { EgForm }, | ||
| 31 | data() { | 16 | data() { |
| 32 | return { | 17 | return { |
| 18 | + model: {}, | ||
| 33 | option: { | 19 | option: { |
| 34 | - groups: ['basic', 'location'], | ||
| 35 | list: [ | 20 | list: [ |
| 36 | - { type: 'el-input', label: '名称', key: 'name' }, | ||
| 37 | - { type: 'el-input', label: '地址', key: 'location' }, | ||
| 38 | - ], | ||
| 39 | - list2: [ | ||
| 40 | { | 21 | { |
| 41 | - group: { title: 'basic', span: 12 }, | 22 | + group: { title: '基础信息', span: 12 }, |
| 42 | list: [ | 23 | list: [ |
| 43 | { type: 'el-input', label: '名称', key: 'name' }, | 24 | { type: 'el-input', label: '名称', key: 'name' }, |
| 44 | - { type: 'el-input-number', label: '名称1', key: 'name1' }, | ||
| 45 | - { type: 'el-switch', label: '名称2', key: 'name2' }, | ||
| 46 | - { type: 'el-input', label: '名称3', key: 'name3' }, | 25 | + { type: 'el-input-number', label: '年龄', key: 'age' }, |
| 47 | ], | 26 | ], |
| 48 | }, | 27 | }, |
| 49 | { | 28 | { |
| 50 | - group: 'location', | 29 | + group: { title: '住址', span: 24, key: 'location' }, |
| 51 | list: [ | 30 | list: [ |
| 52 | - { type: 'el-input', label: '地址', key: 'location' }, | 31 | + { type: 'el-input', label: '地址简称', key: 'locationMin' }, |
| 32 | + { | ||
| 33 | + group: { span: 12, key: 'district' }, | ||
| 34 | + list: [ | ||
| 35 | + { type: 'el-input', label: '省', key: 'province', span: 24, rules: [{ required: true, message: '请输入省' }] }, | ||
| 36 | + { type: 'el-input', label: '市', key: 'city', span: 24 }, | ||
| 37 | + ], | ||
| 38 | + }, | ||
| 39 | + { | ||
| 40 | + group: { title: '小区信息', span: 24 }, | ||
| 41 | + list: [ | ||
| 42 | + { type: 'el-input', label: '小区名', key: 'areaName', span: 24 }, | ||
| 43 | + { type: 'el-input', label: '门牌号', key: 'homeNum', span: 24 }, | ||
| 44 | + { | ||
| 45 | + group: { title: 'A栋', span: 24 }, | ||
| 46 | + list: [ | ||
| 47 | + { type: 'el-input', label: '人数', key: 'anumber', span: 24 }, | ||
| 48 | + ], | ||
| 49 | + }, | ||
| 50 | + { | ||
| 51 | + group: { title: 'B栋', span: 24, key: 'bside' }, | ||
| 52 | + list: [ | ||
| 53 | + { type: 'el-input', label: '人数', key: 'bnumber', span: 24 }, | ||
| 54 | + ], | ||
| 55 | + } | ||
| 56 | + ], | ||
| 57 | + } | ||
| 53 | ], | 58 | ], |
| 54 | }, | 59 | }, |
| 55 | - { type: 'el-input', label: '名称', key: 'name' }, | ||
| 56 | - { type: 'el-input', label: '地址', key: 'location' }, | ||
| 57 | - { type: 'el-input-number', label: '名称1', key: 'name1' }, | ||
| 58 | - { type: 'el-switch', label: '名称2', key: 'name2' }, | ||
| 59 | - { type: 'el-input', label: '名称3', key: 'name3' }, | 60 | + { type: 'el-input', label: '身高', key: 'height' }, |
| 61 | + { type: 'el-input', label: '体重', key: 'weight' }, | ||
| 60 | ] | 62 | ] |
| 61 | } | 63 | } |
| 62 | } | 64 | } |
| 63 | }, | 65 | }, |
| 66 | + mounted() { | ||
| 67 | + setTimeout(() => { | ||
| 68 | + this.model = { | ||
| 69 | + age: 7, | ||
| 70 | + name: '1', | ||
| 71 | + location: { | ||
| 72 | + locationMin: 'a', | ||
| 73 | + district: { | ||
| 74 | + province: 'p', | ||
| 75 | + city: 'c' | ||
| 76 | + }, | ||
| 77 | + areaName: 'a', | ||
| 78 | + homeNum: 'n', | ||
| 79 | + anumber: '1', | ||
| 80 | + bside: { | ||
| 81 | + bnumber: '2' | ||
| 82 | + } | ||
| 83 | + }, | ||
| 84 | + height: '3', | ||
| 85 | + weight: '4' | ||
| 86 | + } | ||
| 87 | + }, 3000); | ||
| 88 | + }, | ||
| 64 | methods: { | 89 | methods: { |
| 90 | + onValidate(v) { | ||
| 91 | + console.log(v); | ||
| 92 | + }, | ||
| 93 | + handleGetValue() { | ||
| 94 | + this.$refs.form.validate(); | ||
| 95 | + } | ||
| 65 | } | 96 | } |
| 66 | } | 97 | } |
| 67 | </script> | 98 | </script> |
| 68 | \ No newline at end of file | 99 | \ No newline at end of file |