代码优化-无限循环列表

无限循环列表Vue实现

为了实现上次的承诺请看这里,我分装了一个组件,主要的功能是:

  1. 自动滚动
  2. 无限循环
  3. 不断请求数据

系统里面有类似的组件(基于happy-scroll实现),但是除了不太好用之外,功能上没有实现无限循环以及只能展示固定的数据。

演示地址,这个演示只能实现单向滚动,跟我要实现的不太一样,不过莫急,看

好像不是很直观,可以看右边的滚动条,到了顶部和底部会自动加载数据数据,滑到顶部会自动滚动到请求数据的第一条数据,看下图

使用

代码优化-无限循环列表_第1张图片

组件名:esay-auto-scroll-list

属性:

属性

width

设置组件的宽

height

设置组件的高

haveData

状态,是否有数据

loading

状态,是否在加载数据(请求数据是否返回)

flag

每个ul的唯一标志,ul必须增加data-flag的自定义标签

notice

当滚到底/顶部的回调函数

注意点

  1. 组件只是实现数据的滚动,以及滚动到边界(顶/底)调用回调函数,具体要实现无限上下滚动 or 单向有限滚动 or 其他,需要回调函数的配合(在线实例和博客动图就是回调函数的不同,效果就不一样)
  2. haveData和loading是根据实际返回数据设置的。在发送请求前,havaData=false loading=true。请求结束后,haveData根据实际情况设置,loading=false

组件

组件源码,注意也要使用config.js配置文件,在项目总请使用 autoScrollList实际使用版本.vue

知识点

clientHeight
跟元素的滚动和位置无关,代表元素的高度,包括padding但不包括border、水平滚动条、margin的元素的高度。对于inline的元素这个属性一直是0,单位px,只读属性

代码优化-无限循环列表_第2张图片

offsetHeight
跟元素的滚动和位置无关,代表元素的高度,包括padding、border、水平滚动条,但不包括margin的元素的高度。对于inline的元素这个属性一直是0,单位px,只读属性

代码优化-无限循环列表_第3张图片

scrollHeight
跟滚动条有关(子元素高于父元素),代表当前不可见部分的高度,可见部分就是clientHeight,单位px,只读属性

代码优化-无限循环列表_第4张图片

判断是否滑到底部: ele.scrollHeight - ele.scrollTop ==== ele.clientHeight

scrollTop
代表在有滚动条时,滚动条向下滚动的距离也就是元素顶部被遮住部分的高度。在没有滚动条时scrollTop==0恒成立。单位px,可读可写属性

代码优化-无限循环列表_第5张图片

offsetTop
它返回当前元素相对于其 offsetParent 元素的顶部的距离(子边框外侧到父边框的内存的距离),单位px,只读属性
clientTop
一个元素顶部边框的宽度,不包括顶部外边距或内边距。可以理解成定义border的高度,单位px,只读属性

基本思路

上滑顶部:当发出请求前(调用回调函数前),保存当前列表中的第一条数据以及scrollTop和offetHeight。当请求结束后,更新完数据,将保存的数据插入到最新数据的后面,并更新scrollTop保持视觉上的连续性。

下滑到底部:当发出请求前(调用回调函数前),保存当前列表最后一条数据以及scrollTop和offetHeight。当请求结束后,更新完数据,将保存的数据插入到最新数据的前面,并更新scrollTop保持视觉上的连续性。

注意点

  1. 保存的的offsetHeight是多个子元素的offsetHeight的集合
  2. 使用insertBefore插入的元素,在下一次更新数据时,可能还会保存,需要去除多余的子元素(唯一标志flag的作用)
  3. 最后一组数据比较特殊,数量可能没有最开始请求那么多。例如设置的请求数量是10条,但最后一组数据可能只有1条,需要特殊处理。

回调函数

回调函数是实现需要效果的关键,就是看你怎么处理边界位置的情况,下面是我的实例:

async loadData(type){

this.loading = true

this.moreData = false

this.flag++

let page

if(type === scrollDir.down){

if(this.endPage === this.totalPage){

this.endPage = 1

this.startPage = this.totalPage

}else{

const newStartPage = (this.startPage+1)%this.totalPage

const newEndPage = (this.endPage+1)%this.totalPage

this.endPage = newEndPage===0? this.totalPage: newEndPage

this.startPage = this.endPage%this.totalPage - 1>0? this.endPage%this.totalPage - 1: this.totalPage

}

page = this.endPage

}else if(type === scrollDir.up){

if(this.startPage<=1){

this.startPage = this.totalPage

this.endPage = 1

}else{

const newStartPage = this.startPage-1

const newEndPage = this.endPage-1

this.startPage = newStartPage>0? newStartPage:1

this.endPage = this.startPage%this.totalPage + 1

}

page = this.startPage

}

this.investProjectList = await this.getInvestProjectsData({page})

this.totalPage = this.investProjectList.pages

this.moreData = true

this.loading = false

},

注意点
  1. 需要定义startPage 和 endPage两个变量跟踪page变化,之所以要两个变量是因为当前可视窗口可以存在多个子元素

代码优化-无限循环列表_第6张图片

  1. 上滑endPage根据startPage变化,下滑startPage根据endPage变化

总结

这次实现这个功能用的时间太长了,写到一半的时候发现不行,又推到重来了,浪费了很多时间,会这样还是因为自己前期没有考虑仔细就开始写代码,连写什么东西都不明确,需要反思。

你可能感兴趣的:(vue.jshtml5前端)