【vant】list组件无限/自动加载数据

2,520 阅读4分钟

开发使用vant的list组件时,会自动加载数据。网上查阅了资料,有以下处理方案:

  1. 保证父级至根元素没有overflow-y: scroll属性

  2. list组件设置 height: xxx; overflow: scroll;

根据第一点,代码样式中并没有overflow-y: scroll。根据第二点,可以实现,但业务不需要设置列表的高度,故不适用(可以动态计算,看上去列表是铺满页面的)
因为网上没有比较合理的解释,所以看了一下list源码,是如何实现监听滚动到底部的(结果请看移步到最后)

## 查阅list组件,滚动时调用check方法判定是否加载

if (direction === 'up') {  isReachEdge = scrollerRect.top - placeholderRect.top <= offset;} else {
  // 默认走这边  isReachEdge = placeholderRect.bottom - scrollerRect.bottom <= offset;}

根据以上代码,可以知道placeholderRect和scrollerRect是主要判定是否滚动的主要元素。

placeholderRect

var placeholderRect = _this.$refs.placeholder.getBoundingClientRect();

可以明显看出,这个元素属于list组件,打印一下可以知道这是list组件最下边的一个占位符

scrollerRect

var el = _this.$el,    scroller = _this.scroller;var scrollerRect;if (scroller.getBoundingClientRect) {
  scrollerRect = scroller.getBoundingClientRect();} else {  scrollerRect = {    top: 0,    bottom: scroller.innerHeight  };}

 根据以上代码块可得出,scrollerRect值是由scroller决定得,并且scroller有两种情况。那咱就继续看scroller吧。

export default createComponent({
  mixins: [BindEventMixin(function (bind) {    if (!this.scroller) {      this.scroller = getScroller(this.$el);    }    bind(this.scroller, 'scroll', this.check);  })],})

BindEventMixin做了事件的绑定和销毁,咱们这里主要看getScroller方法

var overflowScrollReg = /scroll|auto/i;
export function getScroller(el, root) {
  // 因为调用时没传入root,故默认元素为window  if (root === void 0) {    root = window;  }  var node = el;
  // 从传入元素开始向上遍历,找到元素样式overflow-Y为scroll或者auto时,返回  while (node && node.tagName !== 'HTML' && node.tagName !== 'BODY' && node.nodeType === 1 && node !== root) {    var _window$getComputedSt = window.getComputedStyle(node),        overflowY = _window$getComputedSt.overflowY;        console.log(22, node, _window$getComputedSt)    if (overflowScrollReg.test(overflowY)) {      return node;    }    node = node.parentNode;  }
  return root;}

现在知道scroller出现的两种情况了:

  1. list组件从自身向上层遍历,知道找到某个元素的overflow-y为scroll或者auto时返回

  2. 上面条件不符合,返回传入的元素root(这里默认是window)

根据以上两种情况,继续1回来分析

isReachEdge = placeholderRect.bottom - scrollerRect.bottom <= offset;

当scroller符合条件2时,scrollerRect.bottom 为当前窗口显示区域的高度,这样是可以计算出来的
当scroller符合条件1时,scrollerRect.bottom 为符合元素底部距离窗口顶部的距离,这样也是可以计算出来的

那么咱们无限触发是怎么产生的呢?

条件1除了元素需要overflow-y为scroll或者auto之外,还需要给定高度!最终咱们总结了两种使用场景:

条件1适用场景为,用户想在指定高度的元素中使用list组件(height: xxx; overflow-y: scroll | auto;)

条件2适用场景为,用户想简单使用列表,铺满屏幕(保证父级至根元素没有overflow-y: scroll | auto)

至此本次问题就分析完毕,大家可以根据场景自由发挥。

然而,我想使用条件2,并且父级至根元素没有overflow-y: scroll | auto,还是会自动加载!!!最后用源码debug发现,父级给了 overflow-x: hidden之后,overflow-y变为了auto, 又学到了!