问题描述
整个页面是个大的表单,里面嵌套了多个子组件,最终在保存时在父页面统一校验。出现的问题是如果子组件内部相关元素发生变化时会触发外层校验,但这并不是想要的效果,想要的效果是只有最终在点击保存的时候再去触发校验。示例代码如下:
// parent.vue
<template>
<el-form :rules="rules" :form="form" ref="form">
<el-form-item prop="name" label="组件1">
<child-component v-model="form.name"></child-component>
</el-form-item>
... ...
<el-button @click="save">保存</el-button>
</el-form>
</template>
<script>
import ChildComponent from './child.vue'
export default {
components: {
ChildComponent
},
data () {
return {
form: {
name: ''
},
rules: {
name: [
{ required: true, message: '请选择', trigger: 'change' }
]
}
}
},
methods: {
// 最后保存时进行整体校验
save () {
this.$refs['form'].validate()
}
}
}
</script>
子组件内部主要是通过一定的查询条件调用接口得到相应的数据,通过手动勾选查询后的数据,暴露给父页面。
// child.vue
<template>
<div>
<!-- 筛选条件 -->
<el-select v-model="form.value" clearable>
<el-option label="电脑" value="1"></el-option>
</el-select>
<el-button @click="search">查询</el-button>
<!-- 表格数据 -->
<el-table
border
:data="tableData"
@selection-change="handleSelectionChange">
<el-table-column
type="selection"
width="55">
</el-table-column>
<el-table-column
prop="name"
label="名称">
</el-table-column>
... ...
</el-table>
</div>
</template>
<script>
export default {
data () {
return {
tableData: [],
form: {
value: ''
}
}
},
methods: {
// 数据查询
search () {},
// 把勾选的数据暴露给父页面
handleSelectionChange (val) {
this.$emit('input', val)
}
}
}
</script>
ElSelect数据发生改变后会触发外层的校验,清空下拉框选项后会出现错误提示语。
原因
通过查看Element相关源码,可以看到对于ElSelect组件内部监听了其value值,一旦发生变化就会触发ElFormItem的校验方法。
其实不止是
ElSelect组件,还有ElRadioGroup、ElCheckBox等等组件也存在同样的情况,本文就不一一列举了,感兴趣的大家可以自行查看。
解决方案
方案一(推荐)父页面改变DOM结构
把子组件拿到外层,这样的话组件内部无论怎么操作都不会触发ElFormItem的校验。但需要保留相关ElFormItem,因为保存时,如果未通过校验需要展示错误提示语。
// parent.vue
<template>
<el-form :rules="rules" :form="form" ref="form">
<child-component v-model="form.name"></child-component>
<el-form-item prop="name" label="组件1"></el-form-item>
... ...
</el-form>
</template>
方案二、子组件内部嵌套ElFormItem,切断校验触发
// child.vue
<template>
/* 嵌套el-form-item */
<el-form-item>
<el-select v-model="form.value" clearable>
<el-option label="电脑" value="1"></el-option>
</el-select>
<el-button @click="search">查询</el-button>
<!-- 表格数据 -->
<el-table
border
:data="tableData"
@selection-change="handleSelectionChange">
<el-table-column
type="selection"
width="55">
</el-table-column>
<el-table-column
prop="name"
label="名称">
</el-table-column>
... ...
</el-table>
</el-form-item>
</template>
通过以上方案,保证子组件只负责抛出数据,并不会触发校验操作。