本文共 2285 字,大约阅读时间需要 7 分钟。
前几天的需求开发中,需要完成这样一个功能:
这还不简单?一个横向滚动的tag选择功能。一个横向scroller搞定问题。
但是做为一个对自己有“要求”的程序员,怎么可能会接受一个死气沉沉的滚动条。为了勾起用户的点击欲望,我毫不犹豫的增加了一个点击tag以后,tag自动移动到屏幕左侧位置的动画(如果内容不够,就不滚动)。看着流畅的动画,我在内心给自己点了好几个赞(最后一句忽略)。
上线当天,测试的一个bug打破了我内心的小平静。在Ios手机上面出现了一个意想不到的问题:内容不够的情况,本不应该滚动的滚动条,奇迹般的滚动了!
期望的效果 | 实际的样子 |
---|---|
![]() | ![]() |
最严重的问题是滚过去的tag,再也滚不回来了
bug就在眼前,必须搞定!
在正式分析之前为表述方便做两个重要约定:
【重要约定】
scroller内容不足:scroller内部内容长度小于容器长度
scroller内容充足:scroller内部内容长度大于容器长度
老规矩-控制变量法 为了排除自身代码以及飞猪APP的干扰,在dotwe平台上面使用最少的代码实现了一个。并且用最新的手淘ios版本做了实验。
结果:果然不行。本不应该滚动的scroller还是发生了滚动,并且无法滚动回去。这应该是scroller的bug无疑了。
scroller内容充足时滚动采用来验证。
结果:scroller内容充足的情况下滚动正常。
老规矩上例子:。
结果:经过测试list确实也发生了滚动,但是滚动以后还是可以正常拉回来。不会出现内容被截断的bug。
【问题构成因素】
2.采用如下方式进行滚动
dom.scrollToElement(first, {offset: 0});
【现象】出现异常滚动。并且滚动以后,会出现内容截断,无法滚动回去。内容足够的情况下没有问题。
【范围】
该bug,仅存在在scroller组件,list组件不存在。这个是最治本的方式,但是发版就在眼前,不可能等到下个版本。在将问题反馈给手淘同学以后,赶快思考绕过的方法。
通过自动增加scroller内容的长度,将原本scroller内容不足编程scroller内容充足。
最自然的思维方式。但是也有很多的局限:在整个scroller 内容部分的最后面,增加一个bottom模块。如果scroller渲染完成的时候bottom模块appear,那么意味着内容是满足不了滚动需求的。这时候取消滚动动画。如果是没有appear那么意味着内容比较多可以滚动。
这种思路局限:上面的思路都有这样或者那样的局限,有没有更好的方法呢?
其实只要能获取scroller元素中最后一个view在屏幕中的位置,就能判断出当前的scroller中的内容是否能满足滚动要求。问题就迎刃而解了。 在weex官方文档中,dom模块有一个方法dom.getComponentRect()
通过改方法能获取任一view在屏幕中的位置。那么scroller元素中最后一个view在屏幕中的位置可以获取到么?
答案是可以的:因为scroller中的view并不复用,数据绑定以后,所有的view都已经加载到scroller中。只要在最后一个view上面加上ref的索引,既可获得该view在屏幕中的位置。通过跟scroller容器在屏幕中的区域大小进行比较,就能准确判断出是否满足滚动需求。//针对我自己的业务需求判断代码如下:(仅供参考)isCanScroll: function () { let that = this; dom.getComponentRect(this.$refs.rightBottomCell, option => { console.log('getComponentRect:', option); let size = option.size; if (size) { let left = Math.round(size.left); if (left > 750) { that.isCanScrollFlag = 1; that.scrollToLeftOnly(); } else { that.isCanScrollFlag = 0; } } }); }
至此问题圆满解决!
转载地址:http://bavml.baihongyu.com/