文章目录
- 概要
- 整体架构流程
- 技术名词解释
- 技术细节
概要
提示:这里可以添加技术概要
正常情况下,el-table可编辑表格,如果输入框内容不合理的情况下,错误提示会显示在el-input下方对应。
但是,我不得不将错误提示放到el-tooltip中显示,因为产品给出的校验失败信息实在是太太太太太长长长长长长了!!!
其余“必填”,“请输入整数”之类的常见语句咱就不说了,来感受一下表单项的超长校验不通过提示:
由英文字母开头,只能包含英文字母、数字和下划线,最长32位,不能以下划线结尾
这句话放到表单里还舒展得开,但领导要求不允许另开弹框,只能在表格里编辑。表格列只有那么宽,表中还有那么多项,强制塞进去后,一行内各个不通过的校验提示开始打架:
①错误校验提示被其他列截断遮挡
②强制调整.el-form-item__error
的宽度,错误校验提示底部文字被下一行tr遮挡
③设置定位,控制.el-form-item__error
不被遮挡,该校验下一项也不通过时,这个超长校验提示戳到了下一个校验文字的脸上
((ˉ▽ˉ;)…)
整体架构流程
为了方便举例这里只放一个表单项说明
假设需要为学生录入信息,其中有一项是学生标识,要求该标识的命名规则为:由英文字母开头,只能包含英文字母、数字和下划线,最长32位,不能以下划线结尾
html部分:
<template>
<div>
<el-form :inline="true" :model="stuForm" ref="stuForm">
<el-table :data="stuForm.stuData" @row-click="getRow" @current-change="clickCurrent" tooltip-effect="light">
<el-table-column prop="code" label="标识:" align="center" :show-overflow-tooltip="true">
<template v-slot="scope">
<div class="edit-table">
<!--编辑部分-->
<el-form-item v-show="scope.row.isEdit"
:prop="'stuData.'+scope.$index+'.code'"
:rules="[{validator:(rule,value,callback)=>{checkCodeValue(rule,value,callback,scope.row)}}]">
<el-tooltip
:disabled="scope.row.ms1&&scope.row.ms2"
:content="scope.row.ms1?errorMess1:errorMess2"
placement="top" effect="light">
<el-input v-model="scope.row.code" @blur="subRow(scope.$index,scope.row)"/>
</el-tooltip>
</el-form-item>
<!--展示部分-->
<el-tooltip :content="scope.row.code" placement="top" effect="light">
<span v-show="!scope.row.isEdit"
class="long-data-show">{{scope.row.code}}</span>
</el-tooltip>
</div>
</template>
</el-table-column>
</el-table>
</el-form>
</div>
</template>
js处理:
<script>
export default {
data(){
return {
errorMess1:"由英文字母开头,只能包含英文字母、数字和下划线,最长32位,不能以下划线结尾",
errorMess2:"必填项不能为空",
stuForm:{stuData:[]},//学生信息列表
}
},
mounted(){this.loadData()},//初始化加载后台数据
methods:{
loadData(){
//假设如下是获取学生信息的接口,加载后端分页第一页数据,每页10条
//getStudentData({page:1,size:10}).then(res => {
//初始化需要自己处理下数据,添三个属性
let res = {data:[{code:'abc'},{code:'efg'}]}//模拟接口数据
this.stuForm.stuData = [];
//isEdit=是否显示输入框,ms1对应32位校验是否显示错误信息,ms2对应非空校验是否显示错误信息
this.stuForm.stuData = res.data.map(item => {return {...item,isEdit:false,ms1:true,ms2:true}})
//})
},
checkCodeValue(rule,value,callback,row){//表单项单独校验处理
let reg = /^[a-zA-Z]([a-zA-Z0-9_]{0,30}[a-zA-Z0-9])?$/;
if(value === null || (value.toString().length === 0)){//非空校验
row.ms1 = false;//非空不通,将另一32校验设为false,使disabled失效
row.ms2= true;//非空不通,显示内容为非空校验错误提示,对应errorMess2
callback(new Error(" "))//el-form自带提示处空白占位
} else {//32位格式校验
//同以上原理:都通,均设true使disabled触发;32校验不通,显示32校验的错误信息
reg.test(value) ? (row.ms1 = true, row.ms2 = true, callback())
:(row.ms1 = true, row.ms2 = false, callback(new Error(" ")));
}
},
//其余辅助功能
//点击表格其余行,关闭上次操作行的编辑框(可选择)
clickCurrent(n,o){//对应newValue,oldValue,不明白可以去看下官网
if(o)//o.isEdit = false;//直接关闭上一行编辑状态,或者:(看下一行)
//下面这行看个人要求,如果想要校验规则不通过的行保持编辑状态,可额外加条件限制
if(o.code.trim().length!==0)o.isEdit = false;
},
getRow(row){//点击表格行,点击的这行开启编辑输入框状态
row.isEdit = true;
},
//某行失去焦点时提交这行内容给后台,前提是这行所有输入项校验通过
validateRow(form,index){//目标行校验,这里单独拎出一个方法
let result = true;
for(let item of this.$refs[form].fields){//注意:如果是vue3,这里会报错,需要想别的办法
if(item.prop.split(".")[1] == index){//注意:这里是”==“而不是”===“,如果项目采用严格模式,需要用number转换一下
this.$refs[form].validateField(item.prop,err => {
if(err.length)result = false;
})
}
if(!result)break;
}
return result;
},
subRow(index,row){
if(!this.validateRow("stuForm",index))return;//如果该行校验不通过,拒绝提交
//subOne({code:row.code}).then(res => {//提交信息接口
alert('提交成功')
//}).catch(er=>{row.isEdit = true})//如果接口反馈失败,保持输入状态方便识别刚刚编辑的行
}
}
}
</script>
技术名词解释
列表行处理用到的组件内置属性和方法:
1、@row-click
: 点击tr触发。此处用来将点击的行变为编辑状态
2、@current-change
: 当前行发生变化时触发。此处用来(视情况)关闭上一行的编辑状态
3、tooltip-effect="light"
与:show-overflow-tooltip="true"
: 这两个配合使用,当el-table单元格内容超长时,鼠标移入以弹出气泡方式展示超长内容
4、effect="light"
: 气泡样式,有黑白两种
5、@blur
: 输入框失去焦点时触发。此处用来触发整行校验
技术细节
关于校验单独某行的方法:
validateRow(form,index){
let result = true;
for(let item of this.$refs[form].fields){
if(item.prop.split(".")[1] == index){
this.$refs[form].validateField(item.prop,err => {
if(err.length)result = false;
})
}
if(!result)break;
}
return result;
},
1、item.prop
获取到的数据格式:
第一行:stuData.0.code
第二行:stuData.1.code
第三行:stuData.2.code
…
总之,中间的索引对应数据在列表中的行索引,具体根据表单中绑定的:prop="'stuData.'+scope.$index+'.code'"
而来
2、注意:如果在vue3+element-plus的情况下,this.$refs[form].fields
会运行报错undefined,打印监听后发现,高版本和低版本打印的this.$refs.form
结果不相同,暂无解决方法。区别如下: