mint-ui是饿了么提供的一套vue移动组件,使用起来还是很方便的。
其中有一类组件是用于分页加载数据的,比如Infinite Scroll和Loadmore这两个组件。
最近同事在使用Infinite Scroll实现数据分页懒加载时,遇到了一个奇怪的坑,我花了不少时间才定位出来原因,今天就写到博客里记录一下避免以后再次踩坑。
先来看看Infinite Scroll的介绍:
Infinite Scroll的主要属性为v-infinite-scroll和infinite-scroll-distance,v-infinite-scroll为触发加载时执行的函数,infinite-scroll-distance用来指定滑动到距离页面底部多长的距离时触发加载函数。
infinite-scroll-distance的值较大时,触发加载的滑动距离就可以越短,infinite-scroll-distance的值小则需要滑动到更接近底部的位置才会触发加载。
上面的例子实现的效果如下:
1.滑动到页面底部时触发加载:
2.加载完成:
下面是同事写的有问题的代码的大致示例:
其中loadMore方法被配置为Infinite Scroll组件在下滑触发加载时的事件,每次执行loadMore都去用getData用来获取下一页的数据。
这份代码看上去并没有什么问题,但是同事每次执行上面的代码时,后台明明有10条数据可以展示( 分成两页,一页8条,一页2条 ),但是不知道为什么每次都展示空页面。
debug后发现,刚进入这个页面时,由于Infinite Sroll组件可能由于页面没有高度的原因,触发了三次加载,执行了三次loadMore方法。也就是去请求了三次数据,但是看了上面的代码发现即使是执行了三次请求,也并没有什么问题啊,大不了就把10条数据一次全部加载出来而已。
思考了好久之后,我无意间看了一下NetWork里面这三次数据请求的执行返回时间,发现由于一共只有10条数据也就是两页数据的原因,第三次请求虽然是最后发出的,但却是第一个执行完毕返回的,因为数据库里没有第三页的数据,导致第三次请求的执行速度比前两次的块。
然后再来看看上面代码中的这一段:
会发现当list的length为0时,代码将ifHasData的值置为false了,当ifHasData的值为false时就会展示空页面。
说到这里,问题就一目了然了,由于ajax异步请求的原因,导致没有数据的一次请求快与之前的请求返回,然后将将ifHasData的值置为false,之后的请求返回后并没有再将ifHasData的值置为true,导致页面上一致显示的空页面。当然如果第一、二、三次请求是同步请求的话,那么就不会存在上面这种问题。
这个问题的解决方法,再加一个判断,当发现有数据时将ifHasData再置为true即可:
这样在前两次“姗姗来迟”的请求返回,使得list有值之后,会再将ifHasData置为true,这样就能正常展示数据了。
当然我更推荐的一种做法,是使用一个计算属性:
使用计算属性的好处是每当this.list的值发生变化时,ifHasData计算属性的值都会随之更新,因此就不需要再在代码里手工判断了。