form.vue
<template>
<div class="form">
<hr />
<h1>form{{ formData }}</h1>
<el-form
ref="formRef"
:model="formData"
:label-width="labelWidth"
:inline="true"
:label-position="labelPosition"
:label-suffix="labelSubffix"
:size="size"
>
<el-form-item
v-for="(item, index) in formItems"
:key="index"
:prop="item.prop"
:rules="item.rules"
>
<!-- 标签设置 -->
<template #label>
<template v-if="item.tip">
<el-tooltip
class="item"
effect="dark"
:content="item.tip"
placement="top"
>
<span
>{{ item.label }}
<i class="el-icon-warning el-icon--right"></i>
</span>
</el-tooltip>
</template>
<template v-else>
{{ item.label }}
</template>
</template>
<template v-if="item.type == 'input'">
<el-input
v-model="formData[item.prop]"
:placeholder="item.placeholder"
></el-input>
</template>
<template v-else-if="item.type == 'select'">
<el-select
v-model="formData[item.prop]"
:placeholder="item.placeholder"
>
<el-option
v-for="option in item.options"
:key="option.value"
:label="option.label"
:value="option.value"
>
</el-option>
</el-select>
</template>
<template v-else-if="item.type == 'date'">
<el-date-picker
v-model="formData[item.prop]"
type="date"
placeholder="选择日期"
value-format="yyyy-MM-dd"
>
</el-date-picker>
</template>
<template v-else-if="item.type == 'upload'">
<!-- 向回调函数中传递更多的参数 -->
<el-upload
drag
action="https://jsonplaceholder.typicode.com/posts/"
:multiple="item.multiple"
:auto-upload="false"
:file-list="formData[item.prop]"
:list-type="item.listType"
:on-change="
(file, fileList) => {
fileOnChange(item.prop, file, fileList)
}
"
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">
将文件拖到此处,或<em>点击上传</em>
</div>
<div class="el-upload__tip" slot="tip">
只能上传jpg/png文件,且不超过500kb
</div>
</el-upload>
</template>
</el-form-item>
</el-form>
<div class="footer" v-if="showFooter">
<el-button type="primary" icon="el-icon-search" @click="resetForm"
>重置</el-button
>
<el-button
type="primary"
icon="el-icon-upload
"
@click="submitForm"
>提交</el-button
>
</div>
</div>
</template>
<script>
export default {
name: 'MyForm',
// 自定义组件上使用v-model
// 1. 定义model。 2. 需要将model中prop值同时在props中定义
// 父组件通过v-model指令绑定值时会将数据传递给子组件中的modelValue,子组件通过触发"update:modelValue"事件可以通知父组件
model: {
prop: 'modelValue',
event: 'update:modelValue',
},
props: {
modelValue: Object,
formItems: {
type: Array,
required: true,
},
labelWidth: {
type: String,
},
labelPosition: {
// 自定义校验规则
validator: (value) => {
return ['left', 'right', 'top'].includes(value)
},
},
labelSubffix: {
type: String,
},
size: {
validator: (value) => {
return ['medium', 'small', 'mini'].includes(value)
},
},
showFooter: {
type: Boolean,
default: true,
},
},
data() {
return {
formData: {},
}
},
emits: ['update:modelValue'],
created() {
// 表单初始化
for (let item of this.formItems) {
if (item.type == 'upload') {
this.$set(this.formData, item.prop, [])
} else {
// 注意:这里要进行响应式的设置,否则表单控件会无法输入的
this.$set(this.formData, item.prop, '')
}
}
this.$emit('update:modelValue', this.formData)
},
methods: {
fileOnChange(field, file, fileList) {
this.$set(this.formData, field, [...fileList])
this.$emit('update:modelValue', this.formData)
},
resetForm() {
this.$refs.formRef.resetFields()
},
submitForm() {
this.$refs.formRef.validate().then((res) => {
console.log(res)
})
},
},
}
</script>
<style scoped>
.footer {
display: flex;
justify-content: center;
}
</style>
formConfig.js
const formConfig = {
formItems: [
{
type: 'input',
prop: 'name',
label: '姓名:',
placeholder: '请输入姓名',
rules: [{ required: true, message: '请输入活动名称', trigger: 'blur' }],
},
{
type: 'input',
prop: 'age',
label: '年龄:',
placeholder: '请输入年龄',
rules: [
{
validator: (rule, value, cb) => {
if (value === '') {
cb(new Error('请输入年龄'))
} else {
if (isNaN(value)) {
cb(new Error('请输入数字'))
} else {
if (value < 18) {
cb(new Error('年龄要大于18岁'))
} else {
cb()
}
}
}
},
trigger: 'blur',
},
],
},
{
type: 'select',
prop: 'address',
label: '地址:',
placeholder: '请输入地址',
options: [
{
label: '广州市',
value: 'gz',
},
{
label: '上海市',
value: 'sh',
},
{
label: '深圳市',
value: 'sz',
},
],
},
{
type: 'date',
prop: 'birthday',
label: '生日:',
placeholder: '请输入生日',
tip: '祝你生日快乐',
},
{
type: 'upload',
prop: 'uploadData1',
label: '照片:',
placeholder: '请上传照片',
rules: [{ required: true, message: '请上传照片', trigger: 'blur' }],
listType: '.jpg',
},
],
labelWidth: '120px',
labelPosition: 'top',
labelSubffix: '@',
size: 'mini',
}
export default formConfig
Test.vue
<template>
<div>
test:{{ formData }}
<hr />
<my-form v-bind="formConfig" v-model="formData"></my-form>
</div>
</template>
<script>
import MyForm from '@/components/form'
import formConfig from './formConfig'
export default {
data() {
return {
formConfig,
formData: {},
}
},
components: {
MyForm,
},
}
</script>
标签:modelValue,formData,value,label,ui,element,表单,type,prop
From: https://www.cnblogs.com/it774274680/p/17185971.html