Vant-list源码详解

一、源码理解基础之scroll.js

1、1 >>> getScrollEventTarget

export default {
getScrollEventTarget(element, rootParent = window) {
    let currentNode = element;
    while (currentNode && currentNode.tagName !== 'HTML' && currentNode.tagName !== 'BODY' && currentNode.nodeType === 1 && currentNode !== rootParent) {
      const overflowY = this.getComputedStyle(currentNode).overflowY;
      if (overflowY === 'scroll' || overflowY === 'auto') {
        return currentNode;
      }
      currentNode = currentNode.parentNode;
    }
    return rootParent;
  }
}

getScrollEventTarget:

这个函数用于找到“目标容器”,即:有滚动条的dom。

 

1、2>>>  getScrollTop

 getScrollTop(element) {
    return 'scrollTop' in element ? element.scrollTop : element.pageYOffset;
  }

getScrollTop:

获取元素的滚动条高度。

Element.scrollTop 属性可以获取或设置一个元素的内容垂直滚动的像素数。

一个元素的 scrollTop 值是这个元素的顶部到它的最顶部可见内容(的顶部)的距离的度量。当一个元素的内容没有产生垂直方向的滚动条,那么它的 scrollTop 值为0。

 

1、3>>> getElementTop

 getElementTop(element) {
    return (element === window ? 0 : element.getBoundingClientRect().top) + this.getScrollTop(window);
  },

getElementTop:

元素顶部至页面顶部的距离

getBoundingClientRect用于获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置。

 

1、4>>>  getVisibleHeight

  getVisibleHeight(element) {
    return element === window ? element.innerHeight : element.getBoundingClientRect().height;
  },

getVisibleHeight:

获取元素高度

 

二、源码理解之index.vue

重要源码部分

  methods: {
    check() {
      if (this.loading || this.finished) {
        return;
      }

      const el = this.$el;
      const { scroller } = this;
      // scrollerHeight 容器可见高度
      const scrollerHeight = utils.getVisibleHeight(scroller);

      /* istanbul ignore next */
      if (!scrollerHeight || utils.getComputedStyle(el).display === 'none' || el.offsetParent === null) {
        return;
      }
      // scrollTop滚动高度
      const scrollTop = utils.getScrollTop(scroller);
      const targetBottom = scrollTop + scrollerHeight;
      let reachBottom = false;
      /* istanbul ignore next */
      if (el === scroller) {
        reachBottom = scroller.scrollHeight - targetBottom < this.offset;
      } else {
        const elBottom =
          utils.getElementTop(el) -
          utils.getElementTop(scroller) +
          utils.getVisibleHeight(el);
        reachBottom = elBottom - scrollerHeight < this.offset;
      }

      /* istanbul ignore else */
      if (reachBottom) {
        this.$emit('input', true);
        this.$emit('load');
      }
    },

    handler(bind) {
      /* istanbul ignore else */
      if (this.binded !== bind) {
        this.binded = bind;
        (bind ? on : off)(this.scroller, 'scroll', this.check);
      }
    }
  }

最主要的方法是check()

重中之重是这段代码:

const elBottom =
          utils.getElementTop(el) -
          utils.getElementTop(scroller) +
          utils.getVisibleHeight(el);
        reachBottom = elBottom - scrollerHeight < this.offset;

下面我就来解释下这段代码的意思:

 看图一:

图一
图一

 这里用a来表示utils.getElementTop(el)    a=152   代表dom顶部距离page顶部的距离

b表示utils.getVisibleHeight(el)  b=800   代表dom的高度

d表示utils.getElementTop(scroller) 即滚动条的滚动的高度,此时没有滚动,即d=0

c表示scrollerHeight  即整个容器的高度

this.offset可以自定义设定

再来看图二:

图二

 

此时滚动条向下滚动了50

所以现在来看下

a=152

b=800

c=852

d=50

此时有变化的是utils.getElementTop(scroller)

如果我们设定this.offset=10

 reachBottom = elBottom - scrollerHeight < this.offset

                      =a-d+b-c=152-50+800-852=50 < 10

所以 reachBottom=false

所以 reachBottom还未达到触发滚动至底部加载新内容的条件

 

如果我们设定this.offset=55

reachBottom = 50 < 55 = true

所以此时可以触发加载新内容。

 

具体代码可以查看https://github.com/youzan/vant/tree/dev/packages/listhttps://github.com/youzan/vant/tree/dev/packages/utils

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值