配合dom.getBoundingClientRect()方法 实现 el-tab 组件的选项卡懒加载,在滚动到最后一个选项卡时,请求新的选项卡数据。

177 阅读1分钟

选项卡数据后端提供,数量级较大,一屏显示不下。产品提供的解决方案是懒加载选项卡,在滚动到最后一条数据后,再次点击next按钮,便请求新的选项卡数据。项目用的element-ui,el-tab自动带有滚动按钮,是使用transform位移变换来实现的。这里主要是思考的其实是,如何合适的判断用户是否已经滚动到最后一条数据。

这里使用dom对象的getBoundingClientRect()方法,此函数返回一个Rect对象,其中有8个属性,如下:

利用最后一个选项卡dom节点的bottom属性值和其固定大小在页面中的父元素的bottom属性值作比较,若相等,则已经滚动到最后的选项卡节点,便触发请求新的选项卡数据。

// tabVNode为el-tab的vnode对象(可以使用Vue.$refs[]获取)
// data.items为选项卡数组,searchForm为请求选项卡数据时的请求体参数。
addTabEvent(tabVNode, data, searchForm){
  // 给tab的next按钮添加点击事件,在数据到底时获取新数据
  if(!tabVNode){
    return ;
  }
  // 这里获取next按钮的dom节点,并且判断是否已经绑定click事件。
  let nextDom = tabVNode.$children[0].$el.children[1];
  if(nextDom && !nextDom.onclick){
    nextDom.onclick = this.handleTabNext(tabVNode, data, searchForm);
  }
},
handleTabNext(tabVNode, data, searchForm){
  return () => {
    // 获取固定大小的父元素的dom节点
    const scrollDom = tabVNode.$children[0].$el.children[2];
    // 获取最后一个选项卡的dom节点
    const finalDom = tabVNode.$children[0].$el.children[2].children[0].lastChild;
    let scrollDomRect = scrollDom.getBoundingClientRect();
    let finalDomRect = finalDom.getBoundingClientRect();
    /**
      利用最后一个选项卡dom节点的bottom属性值和其固定大小在页面中的父元素的bottom属性值作比较。
    	若相等,则已经滚动到最后的选项卡节点,便触发请求新的选项卡数据。
    */
  	// 此处原本为全等判断。但是遇到了一个特殊的兼容性问题(文末细说),所以改为做差值小于10判断。
    if(Math.abs(scrollDomRect.bottom - finalDomRect.bottom) <= 10){
      if(data.items.length < data.total){
        searchForm.pageIndex++;
        this.getData(searchForm, true);
      }else{
        this.$message.info("已获取所有厂站");
      }
    } 
  }
},

兼容性问题:

本来判断bottom属性值是采用全等判断的,在不同分辨率的屏幕下都是可以兼容的。但是,windows提供了显示缩放功能,有100%,125%(默认),150%等缩放比例。我遇到的bug是,在1980*1080分辨率的屏幕上,默认的125%比例下时,原本应满足情况的两个bottom值相差了1px不到,我认为是缩放的问题,使分辨率计算有了精度丢失。所以这里给了10px的可允许误差值。