vue-cli + Element-ui form表单验证的组件封装
这是在前一次封装的基础上加以完善,上一次的简单封装,使用了slot,render,传参逻辑处理等
·
这是在前一次封装的基础上加以完善,上一次的简单封装,可以看下这里vue+element-ui form表单的简单封装
页面大致如下:
直接上代码~
Form组件封装:EditForm.vue
表单字段rules校验,render,slot等使用
<template>
<el-form
ref="form"
v-bind="computedConfig"
:rules="rules"
:model="data"
>
<el-row>
<el-col
v-for="(item, index) in computedItems"
:key="getItemKey(item, index)"
:md="item.md"
:sm="item.sm"
>
<el-form-item :label="item.label + ':'" :prop="item.prop">
<render-content
slot="label"
v-if="item.labelRender"
:render="item.labelRender"
:data="item"
></render-content>
<slot :name="item.slot" v-bind="{ item }">
<component
v-if="item.component"
:ref="item.ref || `cp-${item.prop}`"
:is="item.component"
:data="data"
v-model="data[item.prop]"
v-bind="item.props"
v-on="item.listeners"
/>
<span v-else>{{data[item.prop]}}</span>
</slot>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script>
const defaultConfig = {
labelWidth: '120px'
}
// 表单字段格式化
const RenderContent = {
props: {
render: Function,
formatter: Function, // 格式化数据
data: Object,
prop: String
},
render (h) {
if (this.render) {
return this.render(h, this.data)
}
let value = this.data[this.prop]
if (this.formatter) {
value = this.formatter(value, this.data)
}
return <span>{value}</span>
}
}
// element UI 组件
const alias = {
input: {
component: 'el-input',
props: {}
},
textarea: {
component: 'el-input',
props: {
type: 'textarea'
}
},
radio: {
component: 'el-radio',
props: {}
},
label: {
component: 'render-content',
props: {}
},
select: {
component: 'el-select',
props: {}
},
datePicker: {
component: 'el-date-picker',
props: {
style: {
width: '100%'
},
"value-format": 'timestamp'
}
}
}
export default {
components: {
RenderContent
},
props: {
formConfig: Object,
formItems: Array,
data: Object
},
computed: {
computedConfig () {
return {
...defaultConfig,
...this.formConfig
}
},
computedItems () {
const itemResult = []
for (const item of this.formItems) {
// 剩余参数语法允许我们将一个不定数量的参数表示为一个数组。theArgs
let {component, showIf, prop, props, ...theArgs} = item
if (typeof showIf === 'function' && !showIf(this.data)) {
continue
}
if (typeof props === 'function') {
props = props(this.data)
}
if (component === 'label') {
props = {
...props,
data: this.data,
prop
}
}
if (alias[component]) {
props = {
...alias[component].props,
...props
}
component = alias[component].component
}
itemResult.push({
component,
prop,
props,
...theArgs
})
}
return itemResult
},
rules () {
let rules = this.computedItems.reduce((total, item) => {
if (item.rules) {
let rules = item.rules
if (typeof rules === 'function') {
rules = rules(this.data)
}
total[item.prop] = rules
}
return total
}, {})
return rules
}
},
methods: {
getItemKey (item, index) {
return `${item.prop}-${index}`
},
validate () {
return new Promise(resolve => {
this.$refs.form.validate(resolve)
})
},
clearValidate (props) { // 清空校验
this.$refs.form.clearValidate(props)
}
}
}
</script>
EditForm组件的使用:
<template>
<div>
<div style="width: 800px;margin: 0 auto;">
<edit-form
ref="editForm"
:form-items="formItems"
:form-config="formConfig"
:data="form"
>
<div slot="actRange2">
<el-select style="width: 100%" v-model="form.actRange2" placeholder="请选择活动区域">
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</div>
</edit-form>
<el-button @click="submit">submit</el-button>
</div>
</div>
</template>
<script>
import EditForm from './EditForm'
export default {
components: {
EditForm
},
data() {
return {
form: {
date: '',
name: '',
address: 'default address',
actRange: '',
actRange2: ''
},
formConfig: {
labelWidth: '120px'
},
formItems: [
{
label: '日期',
prop: 'date',
component: 'datePicker',
labelRender: () => {
return (
<span>
<el-tooltip effect="light" placement="left">
<template slot="content">
请选择日期
</template>
<i class="label-tip-icon el-icon el-icon-question"></i>
</el-tooltip>
日期:
</span>
)
},
md: 12,
sm: 12,
rules: [
{ required: true, trigger: 'change', message: '请选择日期' }
]
},
{
label: '姓名',
prop: 'name',
component: 'input',
props: {
placeholder: 'please enter name'
},
md: 12,
sm: 12,
rules: form => {
return form.date
? [{ required: true, trigger: 'blur', message: '请输入姓名' }]
: []
}
},
{
label: '地址',
prop: 'address',
component: 'input',
props: {
disabled: true,
placeholder: 'please enter address'
}
},
{
label: '活动',
prop: 'activity',
component: 'input',
showIf: () => false,
props: {
disabled: true,
placeholder: 'please enter activity'
}
},
{
label: '范围1',
prop: 'actRange1',
component: 'select',
showIf: () => true,
props: {
style: {
width: '100%'
},
disabled: false,
placeholder: 'please enter activity'
}
},
{
label: '范围2',
prop: 'actRange2',
showIf: () => true,
slot: 'actRange2'
}
]
}
},
methods: {
async submit () {
const valid = await this.$refs.editForm.validate()
if (!valid) {
return
}
console.log(this.form)
}
}
}
</script>
大致的封装逻辑就这样了,需要加以补充的,依葫芦画瓢就行了~~~
更多推荐
已为社区贡献4条内容
所有评论(0)