使用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) { // 校驗通過執(zhí)行的邏輯 } 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) { //校驗通過執(zhí)行邏輯 } 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; //結束語句并跳出語句,進行下個語句執(zhí)行 } // 定位到報錯項 dom.$el.scrollIntoView({ block: 'center', behavior: 'smooth', }); } // 頁面提示未通過校驗字段項, this.$message.error(errorArr[0]); } }); },
4. 拓展(踩坑…)
由于頁面比較復雜分了好幾個子組件,而且子組件中都有需要校驗的表單項,在父組件保存表單前,需要調用各個子組件的表單校驗方法,發(fā)現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) {}
上述代碼在父組件里面不能獲取到組件的校驗狀態(tài),子組件換一個寫法就行了
正確代碼示范:
使用 Promise 來返回表單的是否校驗成功狀態(tài)能在父組件成功拿到了
// 子組件代碼 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校驗失敗時定位到失敗項
需求
提交的表單過長,出現滾動條時,點擊‘確定’觸發(fā)表單檢驗后,頁面看不到的表單項報錯,但是用戶在頁面不能感知到,這時需要將滾動條滾動至校驗失敗項處。
如圖:控制臺提示校驗失敗,頁面顯示正常,用戶無感知。
思路
表單校驗失敗時,失敗項有is-error類,獲取這個元素,使用scrollIntoView()方法。
scollIntoView()將調用它的元素滾動到瀏覽器窗口的可見區(qū)域。
js代碼
moveToErr () { this.$nextTick(() => { let isError = document.getElementsByClassName('is-error') if (isError.length) { isError[0].scrollIntoView({ block: 'center', behavior: 'smooth' }) } }) }
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
解決vue3傳屬性時報錯[Vue?warn]:Component?is?missing?template?or
這篇文章主要給大家介紹了關于解決vue3傳屬性時報錯[Vue?warn]:Component?is?missing?template?or?render?function的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2024-01-01實例詳解Vue項目使用eslint + prettier規(guī)范代碼風格
這篇文章主要介紹了Vue項目使用eslint + prettier規(guī)范代碼風格,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2018-08-08