文章目录
- 一、需求
- 二、技术实现
- 1、需求1的实现
- 2、需求2的实现
- 三、参考文档
一、需求
需要实现2个需求(交互效果):
1、在加载页面后,能自动对表单的错误信息进行标红+提示,如下图所示:
2、弹出框提示,询问用户是否自动定位到异常处,如果选择是,则自动滑动页面
二、技术实现
1、需求1的实现
先来看第一个需求,因为用的是elementUI
的el-form
表单控件,所以第一件事就是去该表单的文档页查看是否有加载页面就校验的方法。
可能大部分人想到的是加载页面后,自动触发validate
方法或事件,其实不用,有一个简单的方法是使用Form-Item Attributes
的error
属性:
参数 | 说明 | 类型 |
---|---|---|
error | 表单域验证错误信息, 设置该值会使表单验证状态变为error ,并显示该错误信息 | string |
具体用法为:
<el-form-item :error="itemCode.validate ? itemCode.validateStr : ''" prop='itemCode.attrName' :rules="itemCode.required ? [{ required: true, message: '请输入' + itemCode.attrName, trigger: 'blur' }] : {}">
<el-input size="small" v-model="itemCode.value" :placeholder="'请输入' + itemCode.attrName"></el-input>
</el-form-item>
代码解释:
当后端API
接口的validate
为true
时,则表示当前表单项是缺失项,会自动显示红框+提示,红框是error
属性给的,只要该属性的值不是"",就会自动显示红色的框。而错误提示是error
属性的值,比如这里的提示为接口返回过来的值:itemCode.validateStr
当你纠正错误后,红框和错误提示会消失。前提是你配置了rules
的验证规则,比如上面的:rules
属性(这个是行内写法,全局的也可以)。
这样第一个需求就解决了。
2、需求2的实现
这个需求就不完全依赖vue
或elementUI
的方法了,这里的问题就在于可能会有多个标红字段,那么只需要自动定位到第一个就行。
交互逻辑是,先判断是否有itemCode.validate
为true
,即异常的项,如果有,再自动弹出comfirm
弹框,询问用户是否需要自动定位,如果需要,则自动定位到第一处异常的表单控件这。
所以需要分两步做,先来判断是否有异常项,因为后端返回的数据是树状结构,会有多层级,我需要遍历递归数组的每一个节点对象是否有itemCode.validate
为true
的项,只要有,那么就整体返回true
,否则返回false
。
代码如下:
hasValidateOne(array) {
// 遍历数组,检查当前项是否有 validate: 1
for (let i = 0; i < array.length; i++) {
//如果有,则返回true
if (array[i].validate === 1) {
return true;
}
// 检查当前项是否有子数组,如果有则递归调用
if (Array.isArray(array[i].childList) && array[i].childList.length > 0) {
if (this.hasValidateOne(array[i].childList)) {
return true;
}
}
}
// 如果遍历完整个数组都没有找到符合条件的项,则返回 false
return false;
}
根据后端给的接口的数据进行调用:
// 检测返回的数据中,是否有缺失项(即校验未通过的原因)
this.isMissingItem = this.hasValidateOne(this.list) || this.hasValidateOne(this.form.customerList);
然后需求1的条件就改为:
<el-form-item :error="itemCode.validate && isMissingItem ? itemCode.validateStr : ''" prop='itemCode.attrName' :rules="itemCode.required ? [{ required: true, message: '请输入' + itemCode.attrName, trigger: 'blur' }] : {}">
<el-input size="small" v-model="itemCode.value" :placeholder="'请输入' + itemCode.attrName"></el-input>
</el-form-item>
接下来就需要实现自动定位,那么怎么知道第一个异常数据项呢?
首先,如果数据异常,会有一个特别的className
,可以使用JS的选择器来选择这个className
。
let el=document.querySelector(".el-form-item__error");
// 或:
let el=document.querySelectorAll(".el-form-item__error")[0];
该选择器会自动选择第一个符合条件的元素,这样这个问题就解决了。
那么怎么自动定位到这里呢?可能我们会想到锚点,或者使用js
的scrollTop
等方法进行距离测量和定位,这样能实现,但是不够便捷,其实JS
有一个一步到位的方法:element.scrollIntoView()
示例和语法:
const element = document.getElementById("box");
// 使用以下任意一种即可
element.scrollIntoView();
element.scrollIntoView(false);
element.scrollIntoView({ block: "end" });
element.scrollIntoView({ behavior: "smooth", block: "end", inline: "nearest" });
考虑到兼容性:
最终的核心代码如下:
this.$confirm("是否要定位到校验未通过的数据项(第一项)", "校验未通过原因查看", {
confirmButtonText: "是",
cancelButtonText: "否",
type: "warning"
})
.then(() => {
const el = document.querySelector(".el-form-item__error");
//如果你的浏览器支持scrollIntoView方法
if (el && el.scrollIntoView) {
el.scrollIntoView({ block: "center", behavior: "smooth" });
} else {
this.$message({
type: "warning",
message: "您的浏览器不支持自动定位,请手动下拉页面定位到校验未通过项!"
});
}
})
.catch(() => {
this.$message({
type: "info",
message: "已取消操作,您可自行下拉页面定位到校验未通过项"
});
});
这样就都解决了。
三、参考文档
1、el-form表单控件文档:https://element.eleme.cn/#/zh-CN/component/form
2、scrollIntoView的方法文档:https://developer.mozilla.org/zh-CN/docs/Web/API/Element/scrollIntoView
如果你在web前端开发、面试、前端学习路线有困难可以加我V:imqdcnn。免费答疑,行业深潜多年的技术牛人帮你解决bug。
加我微信可提供web前端开发,网站开发、技术咨询、答疑、直播讲座等服务
祝你能成为一名优秀的WEB前端开发工程师!