IOS端 vux中scroll滚动自动回弹到顶部或者左侧的解决办法

问题表象

在滑动的时候,偶发性出现自动回弹到顶部的现象,通过onScroll回调发现scrollTop为-1造成回弹,开始寻找为什么scrollTop为-1;

排查问题

1.官网查看例子,发现例子也有,初步断定并不是业务代码的问题
2.查看node_modules文件中的vux的scroll组件
3.发现引用的是node_modules/vux-xscroll组件,找到对应组件

//...
import XScroll from 'vux-xscroll/build/cmd/xscroll.js'
//...

4.找到SimuScroll组件,分析代码,重点查看手势结束事件,因为是松开手指才滚动回去的,最终使用的是SimuScroll库,一个原生滚动,一个是模拟的,
原生滚动应该说的overflow:auto的滚动条,模拟的那个是利用手势加上css3的transform来实现的。

//...
var Util = require('./util'),Base = require('./base'),Timer = require('./timer'),Animate = require('./animate'),Hammer = require('./hammer'),SimuScroll = require('./simulate-scroll'),OriginScroll = require('./origin-scroll');
var XScroll = function(cfg) {//最终使用的是SimuScroll库,一个原生滚动,一个是模拟的var _ = cfg && cfg.useOriginScroll ? OriginScroll : SimuScroll;return new _(cfg);}
//...

5.关注boundryCheckY函数,因为是滚动完才触发的回弹,估计是边界检测出的问题


function _onpanend(e) {var self = this;var userConfig = self.userConfig;var transX = self.computeScroll("x", e.velocityX);var transY = self.computeScroll("y", e.velocityY);var scrollLeft = transX ? transX.pos : 0;var scrollTop = transY ? transY.pos : 0;var duration;if (transX && transY && transX.status == "inside" && transY.status == "inside" && transX.duration && transY.duration) {//ensure the same durationduration = Math.max(transX.duration, transY.duration);}transX && self.scrollLeft(scrollLeft, duration || transX.duration, transX.easing, function(e) {self.boundryCheckX();//重点关注对象});transY && self.scrollTop(scrollTop, duration || transY.duration, transY.easing, function(e) {self.boundryCheckY();//重点关注对象});//judge the directionself.directionX = e.velocityX < 0 ? "left" : "right";self.directionY = e.velocityY < 0 ? "up" : "down";//clear startself.__topstart = null;self.__leftstart = null;return self;}

6.关注isBoundryOutTop和isBoundryOutBottom函数,一个是判断顶部是否越界,一个是顶部是否越界

function boundryCheckY(duration, easing, callback) {var self = this;if (!self.userConfig.boundryCheck) return;if (typeof arguments[0] == "function") {callback = arguments[0];duration = self.userConfig.BOUNDRY_CHECK_DURATION;easing = self.userConfig.BOUNDRY_CHECK_EASING;} else {duration = duration === 0 ? 0 : self.userConfig.BOUNDRY_CHECK_DURATION,easing = easing || self.userConfig.BOUNDRY_CHECK_EASING;}if (!self.userConfig.boundryCheck || self.userConfig.lockY) return;var boundry = self.boundry;if (self.isBoundryOutTop()) {self.scrollTop(-boundry.top, duration, easing, callback);} else if (self.isBoundryOutBottom()) {self.scrollTop(self.containerHeight - boundry.bottom, duration, easing, callback);}return self;}

7.isBoundryOutTop调用的getBoundryOutTop,getBoundryOutTop调用了getScrollTop,所有只需要看getScrollTop函数即可

function isBoundryOutTop() {return this.getBoundryOutTop() > 0 ? true : false;}
function getBoundryOutTop() {return -this.boundry.top - this.getScrollTop();
}
function getScrollTop() {var transY = window.getComputedStyle(this.container)[transform].match(/[-\d\.*\d*]+/g);//alert(window.getComputedStyle(this.container)[transform])//alert(transY[5])//alert(transY)return transY ? Math.round(transY[5]) === 0 ? 0 : -Math.round(transY[5]) : 0;
}

8.alert上面三个关键值,发现是正则写错了,作者是想把数字分割,但没有考虑到科学计数法写法

//
console.log("0,1,2".match(/[-\d\.*\d*]+/g));// ["0", "1", "2"]
console.log("1e100,-1.1e-17,0,1,2".match(/[-\d\.*\d*]+/g));//["1", "100", "-1.1", "-17", "0", "1", "2"]

解决方案

/[-\d\.*\d*]+/g 改为 /[-\d.+e]+/g
优化了一下:中括号内点不用转移,*号并不作为一个数字该有的符合,\d出现了两次可以去掉一个,增加了e和正号

并不能直接更改里面的代码,虽然作者已经不维护了,可以在main.js或者其他初始化的地方增加以下代码(这代码不行,生产翻车了)

try {const scrollPrototype = require('vux-xscroll/build/cmd/simulate-scroll.js').prototype;const Util = require('vux-xscroll/build/cmd/util.js');const transform = Util.prefixStyle("transform");const fnGetScrollTopStr = scrollPrototype.getScrollTop.toString();const fnGetScrollLeftStr = scrollPrototype.getScrollLeft.toString();scrollPrototype.getScrollTop=function () {//此代码有问题,上版本后翻车了,大家引以为鉴return new Function("transform","scrollPrototype","return ("+fnGetScrollTopStr.replace(/\*\\d\*/,"+e")+").call(this)").call(this,transform)};scrollPrototype.getScrollLeft=function () {return new Function("transform","scrollPrototype","return ("+fnGetScrollLeftStr.replace(/\*\\d\*/,"+e")+").call(this)").call(this,transform)};
}catch (e) {}

new Function翻车了,测试环境没一点问题,上了生产就凉了,代码会报错,原因是测试环境并不压缩代码中的变量定义,你定义的transform还是transform
但是生产环境可能就压缩成了单个字母,所以new Function不可取,建议还是常规操作即可

try {const scrollPrototype = require('vux-xscroll/build/cmd/simulate-scroll.js').prototype;const Util = require('vux-xscroll/build/cmd/util.js');const transform = Util.prefixStyle("transform");scrollPrototype.getScrollTop=function () {var transY = window.getComputedStyle(this.container)[transform].match(/[-\d.+e]+/g);return transY ? Math.round(transY[5]) === 0 ? 0 : -Math.round(transY[5]) : 0;};scrollPrototype.getScrollLeft=function () {var transX = window.getComputedStyle(this.content)[transform].match(/[-\d.+e]+/g);return transX ? Math.round(transX[4]) === 0 ? 0 : -Math.round(transX[4]) : 0;};
}catch (e) {}

问题解决

总结

正则内容挺多,还要考虑到贪婪匹配的性能问题,用的好很便利,细节没考虑到就翻车了。

关于科学计数法,可以参考我的另外的一篇文章
parseInt不应该用作 Math.floor的替代品 parseInt脱坑指南

感谢阅读

IOS端 vux中scroll滚动自动回弹到顶部或者左侧的解决办法相关推荐

  1. js中scroll滚动相关

    js中scroll滚动相关 scroll,滚动,一般讨论的是网页整体与浏览器之间的关系. 一.元素相关 属性/方法 解释 element.scrollHeight 返回元素的整体高度. element ...

  2. python运行启动报错解决方法_51testing:iOS自动化测试的那些干货:关于appium启动报错问题的解决办法...

    原标题:51testing:iOS自动化测试的那些干货:关于appium启动报错问题的解决办法 我们在进行iOS Appium自动化测试的时候,会遇到环境配置.兼容使用问题,这里做个总结,以避免后续踩 ...

  3. python2发送http不编码_[转]Python 2.x中常见字符编码和解码方面的错误及其解决办法...

    Python 2.x中的字符编码,设计的的确不好,导致初学者,甚至是即使用Python很长时间的人,都会经常遇到字符编解码方面的错误. 下面就把一些常见情,尽量的都整理出来,并给出相应的解决办法. 看 ...

  4. Linux系统中,python需要import上一级目录文件的解决办法

    Linux系统中,python需要import上一级目录文件的解决办法 在import前添加代码: import sys import os sys.path.append(os.path.abspa ...

  5. ios系统更新后无网络连接网络连接网络连接到服务器,更新iOS 14后无法正常连接是怎么回事?Wi-Fi网络的解决办法[多图]...

    一些用户在升级 iOS 14 之后,发现手机 Wi-Fi 出现了无法连接的问题,非常影响正常使用.最近很多用户在使用更新系统的时候,都出现了使用上的问题,很多用户在使用这款软件的时候,出现了网络不好的 ...

  6. 关于MATLAB中xlswrite函数写数据出现服务器异常情况的解决办法

    关于MATLAB中xlswrite函数写数据出现服务器异常情况的解决办法 参考文章: (1)关于MATLAB中xlswrite函数写数据出现服务器异常情况的解决办法 (2)https://www.cn ...

  7. JS中for循环里面的闭包问题的原因及解决办法

    JS中for循环里面的闭包问题的原因及解决办法 参考文章: (1)JS中for循环里面的闭包问题的原因及解决办法 (2)https://www.cnblogs.com/ZinCode/p/555190 ...

  8. C#中引用第三方ocx控件引发的问题以及解决办法

    C#中引用第三方ocx控件引发的问题以及解决办法 参考文章: (1)C#中引用第三方ocx控件引发的问题以及解决办法 (2)https://www.cnblogs.com/XuPengLB/p/759 ...

  9. 计算机开机自动进入bios,电脑开机自动进入bios界面的原因及解决办法

    电脑开机的时候碰到自动进入BIOS界面,需要按F1才能继续运行,这是怎么回事呢?又该如何解决呢?一般来说有三种原因会导致这种情况.下面给大家详细介绍,需要的朋友参考下吧! 1.原因一:你的BIOS电池 ...

最新文章

  1. JAVA中重写equals()方法的同时要重写hashcode()方法
  2. Ubuntu触摸板使用
  3. Spark集群搭建+基于zookeeper实现高可用HA
  4. js如何实现扫描身份证识别_如何识别身份证上信息?快速录入看这招
  5. python运行不了程序代码_Python源码分析2 - 一个简单的Python程序的执行
  6. 再不解决延迟不当,小心你的内存被打爆
  7. 点评2009年PHP十大图书(2)
  8. 用邮件备份手机数据是必然趋势
  9. Abaqus帮助文档翻译——Abaqus/CAE主窗口介绍
  10. 阿里云新版云计算架构师ACE认证专家解读会重磅来袭
  11. 计算机英语作业答案,大工20春《专业英语(计算机英语)》在线作业1题目【标准答案】...
  12. 分段线性插值法实验报告_试验二 插值法(含实验报告式)格式).doc
  13. AtCoder Beginner Contest 240 C
  14. python调用高德api路径规划_Python调用高德API爬取异地驾驶距离
  15. 常用的mysql函数及在TP中使用示例
  16. Redis:只刷面试题,怎可能进大厂,多理解原理(RDB 持久化、AOF持久化)
  17. Word排版(小计)
  18. 20200509 Curator入门
  19. ESET NOD32 互联网安全软件和防毒软件 -简单,可靠的防护。
  20. latex转word_最有效率的论文排版利器来了,word排版再见吧~

热门文章

  1. 常用的Sql命令之alter
  2. npm install --save 、--save-dev 、-D、-S的区别详细解说
  3. 如何玩好“用户思维”
  4. 内网连接服务器时没有获取凭证页面怎么办?
  5. CentOS 6.5下安装Confluence 5.4
  6. 西南交大大学生营养早餐优化食谱
  7. R语言回归分析-改进异常值
  8. Android——超简单悬浮窗使用教程
  9. HEVC编码视频格式
  10. 照片后期-lightroom常用调色常见参数解