组件页面代码
<template>
<div class="form-block">
<div class="w-form">
<div class="w-field" v-for="(f,f_index) in fields" :key="f_index">
<div class="w-row">
<div class="w-title" :class="f.required?'w-start':''">{{ f.name }}</div>
<div class="w-val">
<input type="text" v-if="f.type==='text'" v-model="formData[f.field]" :placeholder="f.placeholder" :maxlength="f.maxlength">
<input type="digit" v-else-if="f.type==='digit'" v-model="formData[f.field]" :placeholder="f.placeholder" :maxlength="f.maxlength">
<input type="number" v-else-if="f.type==='number'" v-model="formData[f.field]" :placeholder="f.placeholder" :maxlength="f.maxlength">
<radio-group class="w-radio" @change="radioChange($event,f)" v-else-if="f.type==='radio'">
<div class="radio-item" v-for="(r,r_index) in f.radioData" :key="r_index">
<div class="r-val">
<radio :value="r.value" :data-model="f.field"/>
</div>
<div class="r-name">{{ r.name }}</div>
</div>
</radio-group>
</div>
</div>
<div class="f-errors" v-if="errors[f.field]">{{ errors[f.field] }}</div>
</div>
<div class="w-but">
<button @click="handleSubmit">提交</button>
</div>
</div>
</div>
</template>
<script>
export default {
name: "FormPage",
props: {
fields: {
type: Array,
required: true
},
initialData: {
type: Object,
required: false,
default: () => ({})
}
},
data() {
return {
formData: this.initialData,
errors: {}
}
},
methods: {
radioChange(e, f) {
f.radioData.forEach(r => {
if (r.value == e.target.value) {
this.formData[f.field] = r.value
}
})
},
validate() {
this.errors = {}; // 清空上一次的错误信息
let isValid = true;
this.fields.forEach(f => {
if (f.required && !this.formData[f.field]) {
this.errors[f.field] = '必填项不可以为空'
isValid = false;
}
if (['digit', 'number'].includes(f.type) && this.formData[f.field]) {
if (!this.checkNumber(this.formData[f.field], f.checkType)) {
this.errors[f.field] = '请输入正确的数字'
isValid = false;
}
}
});
return isValid;
},
checkNumber: function (number, type) {
switch (type) {
case 1: //手机号
return /^1([3456789])\d{9}$/.test(number);
case 2: //可以有两位小数的数字 金额使用
return /^([0-9])+(\.[0-9]{1,2})?$/.test(number);
case 0:
default: //非零正整数
return /^[1-9]\d*$/.test(number);
}
},
handleSubmit() {
if (this.validate()) {
this.$emit('formSubmit', this.formData);
}
}
},
watch: {
initialData: {
handler(newData) {
this.formData = newData;
this.errors = {}
},
deep: true
}
}
}
</script>
<style scoped lang="scss">
.form-block {
background-color: #EFF2F5;
width: calc(100vw - 40rpx);
height: 100vh;
padding: 20rpx;
position: fixed;
.w-form {
font-size: 24rpx;
padding: 20rpx;
background-color: white;
border-radius: 20rpx;
.w-start::after {
content: '*';
color: red;
}
.w-field {
border-bottom: 1rpx solid #eceeee;
margin-bottom: 20rpx;
display: flex;
flex-wrap: wrap;
width: 100%;
line-height: 60rpx;
.w-row {
display: inline-flex;
width: 100%;
gap: 20rpx;
.w-title {
width: 30%;
}
.w-val {
width: 70%;
input {
padding: 0 15rpx;
height: 100%;
width: 100%;
}
.w-radio {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
.radio-item {
display: flex;
radio {
transform: scale(0.8);
}
}
}
}
}
.f-errors {
color: red;
font-size: 20rpx;
width: 100%;
text-align: right;
}
}
.w-but {
width: 100%;
text-align: center;
margin: 30rpx 0;
button {
background-color: #1989FA;
color: white;
border-radius: 20rpx;
width: 95%;
font-size: 26rpx;
}
}
}
}
</style>
引入例子
<template>
<div>
<FormPage :fields="fields" :initial-data="initialFormData" @formSubmit="formSave"></FormPage>
</div>
</template>