封装组件
基于官网最朴实无华的例子,做了一下延伸。封装的组件,支持一下功能:
- 一行可有多个表单项
- 表单项可赋初始值(如:应用在编辑场景!)
- 可在一个页面上多次复用该组件!
<template>
<div>
<div class="dynamic-wrap">
<div v-for="item in keysList" :key="item">
<a-row :gutter="24">
<a-col :xs="24" :sm="12">
<a-form-item label="姓名" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input
placeholder="请填写姓名"
v-decorator="[
`${title}Name[${item}]`,
{
initialValue: arr[item] ? arr[item].name : undefined,
rules: [
{
required: true,
pattern: /^(?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])+$/,
message: '请填写正确的姓名!'
}
]
}
]"
style="width: 90%; margin-right: 8px"
:maxlength="64"
/>
</a-form-item>
</a-col>
<a-col :xs="24" :sm="12">
<a-form-item label="出生日期" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-date-picker
placeholder="请选择出生日期"
v-decorator="[
`${title}Birthday[${item}]`,
{
initialValue: arr[item] ? moment(arr[item].birthday, 'YYYY-MM-DD') : null,
rules: [{ required: true, message: '请选择出生日期!' }]
}
]"
style="width: 90%; margin-right: 8px"
/>
</a-form-item>
</a-col>
<a-col :xs="24" :sm="12">
<a-form-item label="国籍" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-select
placeholder="请选择国籍"
type="list"
show-search
:filter-option="filterOption"
v-decorator="[
`${title}Country[${item}]`,
{
initialValue: arr[item] ? arr[item].country : undefined,
rules: [{ required: true, message: '请选择国籍!' }]
}
]"
style="width: 90%; margin-right: 8px"
>
<a-select-option v-for="(item, index) in allCountry" :key="item.code">
{{ item.cnFullName }}
</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :xs="24" :sm="12">
<a-form-item label="身份证号" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input
placeholder="请填写身份证号"
v-decorator="[
`${title}IdNumber[${item}]`,
{
initialValue: arr[item] ? arr[item].idNumber : undefined,
rules: [
{
required: true,
pattern: /^[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|10|11|12)(?:0[1-9]|[1-2]\d|30|31)\d{3}[\dXx]$/,
message: '请填写身份证号!'
}
]
}
]"
style="width: 90%; margin-right: 8px"
:maxlength="18"
/>
</a-form-item>
</a-col>
<div v-if="hasAddress">
<a-col :xs="24" :sm="12">
<a-form-item label="住址" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input
v-decorator="[
`${title}Address[${item}]`,
{
initialValue: arr[item] ? arr[item].address : undefined,
rules: [
{
required: true,
message: '请输入住址'
}
]
}
]"
placeholder=""
style="width: 90%; margin-right: 8px"
:maxlength="128"
/>
</a-form-item>
</a-col>
</div>
<div v-else>
<a-col :xs="24" :sm="12">
<a-form-item label="股权百分比(%)" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input
placeholder="请填写股权百分比(%)"
v-decorator="[
`${title}EquityPercentage[${item}]`,
{
initialValue: arr[item] ? arr[item].equityPercentage : undefined,
rules: [{ required: true, pattern: /^\d{1,}$/, message: '请填写正确的股权百分比(%)!' }]
}
]"
style="width: 90%; margin-right: 8px"
:maxlength="3"
/>
</a-form-item>
</a-col>
</div>
<a-col :xs="24" :sm="24" :offset="3">
<a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-button
type="danger"
ghost
class="deleteRowBtn"
v-if="keysList.length > 1"
@click="() => removeRow(item)"
icon="delete"
>
删除
</a-button>
</a-form-item>
</a-col>
</a-row>
</div>
<a-row>
<a-col :xs="24" :sm="24" :offset="3">
<a-form-item>
<a-button type="dashed" class="addRowBtn" @click="addRow" icon="plus">新增</a-button>
</a-form-item>
</a-col>
</a-row>
</div>
</div>
</template>
<script>
import moment from 'moment'
import { AllCOUNTRY } from './country-constant'
export default {
name: 'DynamicForm',
props: {
title: {
type: String,
default: ''
},
hasAddress: {
type: Boolean,
default: false
},
arr: {
type: Array,
default: function() {
return []
}
}
},
data() {
return {
labelCol: {
xs: { span: 24 },
sm: { span: 6 }
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 }
},
allCountry: AllCOUNTRY,
id: 0,
keysList: [],
moment
}
},
created() {
this.form = this.$form.createForm(this)
this.init()
},
methods: {
// 初始化
init() {
const arr = [0]
if (this.arr.length !== 0) {
for (let i = 1; i < this.arr.length; i++) {
arr.push(i)
this.id = this.id + 1
}
}
console.log(this.arr)
this.keysList = arr
},
// 移除某行
removeRow(k) {
if (this.keysList.length === 1) {
// 如果存在可以移除所有行的情况,把条件改为this.keysList.length === 0即可
return
}
this.keysList = this.keysList.filter(item => item !== k)
},
// 新增一行
addRow() {
this.id = this.id + 1
this.keysList = this.keysList.concat(this.id)
},
filterOption(input, option) {
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
}
}
</script>
<style lang="less" scoped>
.dynamic-wrap {
padding-top: 10px;
}
.minusRowBtn {
color: #f5222d;
background: #fff1f0;
border-color: #ffa39e;
padding-right: 7px;
padding-left: 7px;
height: 29px;
margin-left: 10px;
}
.deleteRowBtn {
width: 120%;
margin-left: -6px;
}
.addRowBtn {
width: 80%;
color: #1890ff;
border-color: #91d5ff;
margin-left: -3px;
}
</style>
组件的使用
<template>
<div class="padding: 20px;">
<a-form :form="form">
<dynamic-form
:title="`${PARTONE}`"
:arr="arr"
/>
</a-form>
<a-button style="margin-top: 25px;" type="primary" @click="handleSubmit">
提交
</a-button>
<div style="margin-top: 15px;">{
{ param.field }}</div>
</div>
</template>
<script>
import DynamicForm from './DynamicForm'
const PARTONE = 'partOne'
export default {
name: 'DynamicFormWrap',
components: {DynamicForm },
data () {
return {
form: this.$form.createForm(this),
arr: [ // 模拟从接口获取到的数据(如编辑场景)
{
birthday: "2021-05-16T16:00:00.000Z",
country: "CN",
equityPercentage: "2",
idNumber: "110101199003079913",
name: "深谷",
}],
PARTONE,
param: {
field: '' // 模拟接口接收的参数
}
}
},
methods: {
// 提交
handleSubmit () {
const {form: {validateFields } } = this
validateFields((errors, values) => {
if (!errors) {
const partOneArr = []
values[`${PARTONE}Name`].forEach((item, index) => {
const obj = {
name: values[`${PARTONE}Name`][index],
birthday: values[`${PARTONE}Birthday`][index],
country: values[`${PARTONE}Country`][index],
idNumber: values[`${PARTONE}IdNumber`][index],
equityPercentage: values[`${PARTONE}EquityPercentage`][index]
}
partOneArr.push(obj)
})
this.param.field = JSON.stringify(partOneArr)
}
})
}
}
}
</script>
网友评论