使用el-form之表单校验自动定位到报错位置问题

 更新时间:2023年05月20日 10:17:48   作者:清阿哥、  
这篇文章主要介绍了使用el-form之表单校验自动定位到报错位置问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

1. 背景

表单校验大多数的表单都会用到,一般情况下只是提示当前哪些项校验不通过,但是如果表单比较需要用户自己去找是哪项校验不通过,这样的用户体验不太好,如果能自动定位到当前校验不通过的表单项体验会更好一些(这里是以elementui 的 el-from 组件为例子)

2. 实现思路

目前有两个实现方法:

方法一 

表单校验不通过的时候,会在未校验成功的表单 el-form-item 标签上加一个类名 is-error,可以从这个类名下手,获取当前校验不通过的所有的类名,然后通过 scrollIntoView 方法进行自动滑动到当前报错的表单项位置


方法二 

利用el-form提供的 validate 方法的第二个参数,获取当前校验不通过的rule 对象,获取到报错的 prop 后,在每个需要加表单校验的项上加上 ref,ref 的绑定值和 prop 保持一致这样方便直接定位到哪个prop,然后和第一个方法一样利用 scrollIntoView 方法结合$ref 获取到 $el 实现自动定位到校验不通过的表单项


3. 实现代码

方法一

实现代码:

 	// 表单校验
    verifyForm() {
      this.$refs.basicInfoRule.validate(valid => {
        if (valid) {
          // 校验通过执行的逻辑
        } else {
          // 校验不通过自动定位到不通过的表单项
          this.moveToErr()
        }
      })
    },
    // 自动定位到表单报错项
    moveToErr() {
      this.$nextTick(() => {
        let isError = document.getElementsByClassName('is-error')
        if (isError.length) {
          isError[0].scrollIntoView({
            block: 'center',
            behavior: 'smooth'
          })
	// 这个当滑动到报错项之后自动获取输入框的焦点,方便用户直接进行输入,延迟 800ms 是因为需要都能到定位成功后在进行获取焦点体验更好一些
          setTimeout(() => {
            if (isError[0].previousElementSibling.querySelector('input')) {
              isError[0].previousElementSibling.querySelector('input').focus()
            }
          }, 800)
        }
      })
    }

方法二

实现代码:

模板示例代码

   <el-form-item label="姓名:" prop="name" ref="name">
        <el-input
          v-model.number="form."
          placeholder="请输入姓名"
          clearable
        ></el-input>
      </el-form-item>
 verifyForm() {
      this.$refs.ruleForm.validate((valid, object) => {
        if (valid) {
          //校验通过执行逻辑
        } else {
          let errorArr = [];
          for (let key in object) {
            object[key].forEach((item) => {
              errorArr.push(item.message);
            });
            let dom = this.$refs[Object.keys(object)[0]];
            if (Object.prototype.toString.call(dom) !== '[object Object]') {
              dom = dom[0];
              break; //结束语句并跳出语句,进行下个语句执行
            }
            // 定位到报错项
            dom.$el.scrollIntoView({
              block: 'center',
              behavior: 'smooth',
            });
          }
          // 页面提示未通过校验字段项,
          this.$message.error(errorArr[0]);
        }
      });
    },

4. 拓展(踩坑…)

由于页面比较复杂分了好几个子组件,而且子组件中都有需要校验的表单项,在父组件保存表单前,需要调用各个子组件的表单校验方法,发现el-form 的 validate 方法不能返会校验失败还是校验成功

错误代码示范:

// 子组件代码
   verifyForm() {
      this.$refs.basicInfoRule.validate(valid => {
        if (valid) {
          // 校验通过
          return true
        } else {
          // 校验不通过
          return false
        }
      })
    },
    // 父组件代码
    // 校验子组件表单(通过子组件绑定的ref来调用子组件的校验方法)
    async handleVerify() {
      if (
        !(await this.$refs.basicInfo?.verifyForm()) ||
        !(await this.$refs.priceSetting?.verifyForm())
      ) {
        this.$message.warning('请完善表单必填项')
        return false
      }
      return true
    },
    // 保存
      async saveMainDetail() {
      try {
        if (!(await this.handleVerify())) return
        } catch (e) {}    

上述代码在父组件里面不能获取到组件的校验状态,子组件换一个写法就行了

正确代码示范:

使用 Promise 来返回表单的是否校验成功状态能在父组件成功拿到了

// 子组件代码
 verifyForm() {
      return new Promise((resolve, reject) => {
        this.$refs.basicInfoRule.validate(valid => {
          if (valid) {
            console.log(valid, '校验通过')
            resolve(true)
          } else {
            console.log(valid, '校验不通过')
            reject(new Error())
          }
        })
      })
    }

心得:

实现功能的思路有很多,这里我列举出来的两种,看实际的功能和需求找到适合自己的方法~

el-form校验失败时定位到失败项

需求

提交的表单过长,出现滚动条时,点击‘确定’触发表单检验后,页面看不到的表单项报错,但是用户在页面不能感知到,这时需要将滚动条滚动至校验失败项处。

如图:控制台提示校验失败,页面显示正常,用户无感知。

思路

表单校验失败时,失败项有is-error类,获取这个元素,使用scrollIntoView()方法。

scollIntoView()将调用它的元素滚动到浏览器窗口的可见区域。

js代码

moveToErr () {
  this.$nextTick(() => {
    let isError = document.getElementsByClassName('is-error')
    if (isError.length) {
      isError[0].scrollIntoView({
        block: 'center',
        behavior: 'smooth'
      })
    }
  })
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • vue脚手架搭建过程图解

    vue脚手架搭建过程图解

    vue脚手架是个好东西,能够快速搭建vue单页面应用,vue是基于node环境的,所以要先安装node。下面通过图文并茂的形式给大家介绍vue脚手架搭建过程图解,感兴趣的朋友一起看看吧
    2018-06-06
  • 如何修改vant的less样式变量

    如何修改vant的less样式变量

    这篇文章主要介绍了如何修改vant的less样式变量方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • Vue2和Vue3的10种组件通信方式梳理

    Vue2和Vue3的10种组件通信方式梳理

    这篇文章主要介绍了Vue2和Vue3的10种组件通信方式梳理,本文将通过选项式API 组合式API以及setup三种不同实现方式全面介绍Vue2和Vue3的组件通信方式,需要的朋友可以参考一下
    2022-08-08
  • Vue如何实现组件间通信

    Vue如何实现组件间通信

    组件间通信简单来说就是组件间进行数据传递。就像我们日常的打电话,就是通讯的一种方式,你把话说给我听,我把话说给你听,说的话就是数据。电话就是通讯方式的一种。无论是 Vue 还是 React ,都得进行组件间通信。
    2021-05-05
  • vue axios 二次封装的示例代码

    vue axios 二次封装的示例代码

    本篇文章主要介绍了vue axios 二次封装的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • 详解Vuex的属性

    详解Vuex的属性

    Vuex是专为Vue.js应用程序开发的状态管理模式,这篇文章主要介绍了Vuex的属性,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-08-08
  • vue实现登录、注册、退出、跳转等功能

    vue实现登录、注册、退出、跳转等功能

    这篇文章主要介绍了vue实现登录、注册、退出、跳转等功能,需要的朋友可以参考下
    2020-12-12
  • vite.config配置alias Error: ENOTEMPTY: directory not empty, rmdir

    vite.config配置alias Error: ENOTEMPTY: director

    这篇文章主要为大家介绍了vite.config配置alias时报错:Error: ENOTEMPTY: directory not empty, rmdir解决方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • 使用生成条形码并打印和vue-print-nb以及报错问题的解决

    使用生成条形码并打印和vue-print-nb以及报错问题的解决

    在TypeScript项目中,正确安装vue3-print-nb并配置env.d.ts声明模块,添加tsconfig.json的include路径,确保全局挂载以实现条形码和批量打印功能
    2025-07-07
  • vue-cli-service不是内部或外部命令,也不是可运行的程序或批处理文件问题

    vue-cli-service不是内部或外部命令,也不是可运行的程序或批处理文件问题

    在Vue项目构建过程中,如果遇到无法识别'vue-cli-service'命令的错误提示,通常是因为没有全局安装vue-cli,解决这个问题的步骤主要包括:首先检查Vue版本,如果未安装则先安装Vue;其次全局安装vue-cli;若在安装过程中遇到cnpm命令找不到的情况
    2024-10-10

最新评论