目录
背景 :
项目类似于问卷星里面的问卷调查,当你点击提交按钮时,
页面会有弹窗提醒你有哪些题型未回答,点击确认之后,
页面滚动条会自动跳转至未回答项的 offsetTop 高度位置
以上就是本期所遇到的问题
原代码如下 :
<script> export default { methods: { onSubmit() { this.$refs.reviseForm.validate().then( (res) => this.$emit('submitAnswer', res), (err) => { let unAnswer = []; err.forEach((item) => unAnswer.push(item.name)); unAnswer = Array.from(new Set(unAnswer)); Dialog.alert({ title: '提示', message: `${unAnswer.join('、 ')}题未答!`, }).then(() => { let uaHeight = document.getElementById( 'revise-' + (unAnswer[0] - 1) ).offsetTop; // 重点标记处(原写法用的是是原生方法,指定不行,IOS容易出bug) let scrEle = document.getElementsByClassName('xxx')[0]; // 重点标记处(scrollTo在IOS的兼容性不太好,IOS项目一般都是用scrollTop=n) scrEle.scrollTo({ // 滚动到未答指定位置(IOS未生效) top: uaHeight, behavior: 'smooth', }); }); } ); }, }, }; </script>
解决过程 :
解决方案 :
🈶️ 两点 :
1、document.getElementByClassName ,这是 原生方法,
IOS 有的时候获取不到会很容易出 Bug(经常性获取不到 DOM ),指定不行 。
所以我们需要换一种写法来搞 :
能用 ref 就不用原生的 : this.$refs.xxx.
2、解决问题的关键点 :
IOS 项目一般都是使用 scrollTop
所以 将 scrollTo( ) 替换为 :scrollTop = n 的写法
不用 scrollTo , 改用 scrollTop
( 这里可以判断一下系统,安卓系统完全还是可以使用 scrollTo 的,以保留 smooth 效果 )
最终代码 :
(err) => {
let unAnswer = []; // 未答数组
err.forEach((item) => unAnswer.push(item.name));
unAnswer = Array.from(new Set(unAnswer));
Dialog.alert({
title: '提示',
message: `${unAnswer.join('、 ')}题未答!`,
}).then(() => {
let uaHeight = document.getElementById(
'revise-' + (unAnswer[0] - 1)
).offsetTop;
// 判断是否为 IOS
let u = navigator.userAgent;
let isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); // ios终端
// 重点标记处( 主要代码 )
if (isIOS) {
// IOS 项目一般都是使用 scrollTop = n
this.$refs.ele.scrollTop = uaHeight;
} else {
// 重点标记处(scrollTo在IOS的兼容性不太好)
this.$refs.ele.scrollTo({
top: uaHeight,
behavior: 'smooth',
});
}
});
}
拓展 :
移动端项目一般都是使用的 Vant2 组件库,
的 表单组件 — Form 表单 ,
API 里面有一个 Props 参数 : scroll-to-error ,
但是用上之后并未生效起作用
<van-from :scroll-to-error="true" >
不知道是什么问题所导致的,然后接着往下看到了 另一种解决办法 :
scrollToField 方法 可以帮助我们实现 滚动到对应表单项的位置 ,
因此转换一下思路,咱们可以结合一下 :
validate 方法,.then 的 err 里面可以拿到 field 校验不通过的所有 name 数组,
此时咱们只需要
(err) => { this.$refs.xxx.scrollToField(err[0].name) }
就可以准确定位到 form 表单里面第一个校验出错的位置了。
OK ~ 下课 。