记录一次ElementUI踩坑艰辛历程
最近在工作上遇到了一个需求,具体如下

如果所示:
有一个Select和一个Input这两个组件要组合到一起
我看到这个需求的表情

这不是挺简单的吗??? 要知道熟悉ElementUI
的朋友们,就知道Input
其实就有这个功能

在官方的组件库中
,就已经提供了实例,而且很简单
,so easy
但是事与愿违
,我这里先抛开原有框架的封装的问题
,先来研究一下ElementUI
对于这个组件有什么问题?
我们可以看到一个比较特别点是上面图中证件类型和证件号这两个字段
,都是必填的,我这里写了一个简单demo
界面如下:
一个带Select的Input的框,然后点击立即创建,校验表单,然后提交

正常情况下,操作没有问题

那么假设不输入直接选择立即创建
呢

这时候可以看到,明显Select
,没有去校验,问题出在哪里?
接着我们去分析一下代码
xml
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="150px" class="demo-ruleForm">
<el-form-item label="测试复杂输入框" prop="testInput">
<el-input placeholder="请输入内容" class="input-with-select" v-model="ruleForm.testInput">
<el-select style="width: 200px;" v-model="ruleForm.select" clearable slot="prepend" placeholder="请选择">
<el-option label="餐厅名" value="1"></el-option>
<el-option label="订单号" value="2"></el-option>
<el-option label="用户电话" value="3"></el-option>
</el-select>
<el-button slot="append" icon="el-icon-search"></el-button>
</el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">立即创建</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
校验规则
如下:
yaml
rules: {
testInput: [
{ required: true, message: '请输入内容', trigger: 'blur' }
],
}
那么这时候我们就会发现,其实rule仅仅只是对input进行校验
,没有对select
进行校验,那么我们就要针对select
进行校验
我这时候新增了select校验规则
yaml
rules: {
testInput: [
{ required: true, message: '请输入内容', trigger: 'blur' }
],
select: [
{ required: true, message: '请选择select', trigger: 'change' }
],
}
但是这样肯定是不够的,要知道form
是去根据formItem上的prop
进行校验的,所以还需要对元素进行修改,这里对原本select
外加了一层form-item并且绑定上了prop
ini
<el-input placeholder="请输入内容" class="input-with-select" v-model="ruleForm.testInput">
<el-form-item prop="select" slot="prepend">
<el-select style="width: 200px;" v-model="ruleForm.select" clearable placeholder="请选择">
<el-option label="餐厅名" value="1"></el-option>
<el-option label="订单号" value="2"></el-option>
<el-option label="用户电话" value="3"></el-option>
</el-select>
<el-button slot="append" icon="el-icon-search"></el-button>
</el-form-item>
</el-input>
那么这时候我们再去看一下效果

似乎进行校验了,但是有明显的两个问题
- 提示的文字重叠了
- select框还是没有红色的边框
先处理第一个问题

从图中我们看出两个FormItem的内容
区域重叠了,而提示语
默认是在formItem
顶部进行插入
那么这时候我们去看html的结构

可以看到两个错误替换的html
提示层级不同
,那么这时候就好办了
通过修改框架css
就可以实现我们需要的效果了,这里我们分别对外层和内容的提示进行了样式修改
css
::v-deep .el-form-item {
.el-form-item__error {
left: 200px;
}
.el-input-group__prepend {
// 内层的样式 我们需要恢复原貌
.el-form-item__error {
left: 0px;
}
}
}
最后得到的效果如下:

是不是很完美,但是这时候还得注意一种情况
,我这里只有一个formItem
,如果有多个呢

显示这时候还会出现问题我们需要限定的样式只是特定的FormItem我们给自己的formItem加一个特定的class

最后效果如下,这样我们提示语错乱重叠的问题就处理好了
这效果显然还不是最终的效果
,还有红框的问题没有解决

通过html元素上分析
,发现到如果是未填的表单中有一个isError
的class
,那么我们就可以通过这个class
进行对select
框的选取

最后修改后的效果,完成符合我们的需求

闲谈
不得不说,处处是坑啊,原以为一个简单需求,最后实现起来这么多问题,笔者心里苦,感觉工作上经常遇到这种问题,看似简单的问题,里面牵扯到许多的东西。
虽然各位在此看起来可能比较简单,但是如果放在一个复杂的组件中呢。

一个组件修改差点要了一条老命

不过幸好最后还是艰难的做出来了。