使用el-form之表單校驗自動定位到報錯位置問題
1. 背景
表單校驗大多數(shù)的表單都會用到,一般情況下只是提示當前哪些項校驗不通過,但是如果表單比較需要用戶自己去找是哪項校驗不通過,這樣的用戶體驗不太好,如果能自動定位到當前校驗不通過的表單項體驗會更好一些(這里是以elementui 的 el-from 組件為例子)
2. 實現(xiàn)思路
目前有兩個實現(xiàn)方法:
方法一
表單校驗不通過的時候,會在未校驗成功的表單 el-form-item 標簽上加一個類名 is-error,可以從這個類名下手,獲取當前校驗不通過的所有的類名,然后通過 scrollIntoView 方法進行自動滑動到當前報錯的表單項位置

方法二
利用el-form提供的 validate 方法的第二個參數(shù),獲取當前校驗不通過的rule 對象,獲取到報錯的 prop 后,在每個需要加表單校驗的項上加上 ref,ref 的綁定值和 prop 保持一致這樣方便直接定位到哪個prop,然后和第一個方法一樣利用 scrollIntoView 方法結合$ref 獲取到 $el 實現(xiàn)自動定位到校驗不通過的表單項

3. 實現(xiàn)代碼
方法一
實現(xiàn)代碼:
// 表單校驗
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)
}
})
}方法二
實現(xiàn)代碼:
模板示例代碼
<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ā)現(xiàn)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())
}
})
})
}心得:
實現(xiàn)功能的思路有很多,這里我列舉出來的兩種,看實際的功能和需求找到適合自己的方法~
el-form校驗失敗時定位到失敗項
需求
提交的表單過長,出現(xiàn)滾動條時,點擊‘確定’觸發(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-office插件實現(xiàn)word預覽功能
vue-office是一個支持多種文件(docx、.xlsx、pdf)預覽的vue組件庫,支持vue2和vue3,這篇文章主要介紹了Vue3使用vue-office插件實現(xiàn)word預覽功能,需要的朋友可以參考下2024-04-04
解決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

