| | |
| | | class="c-infinite-scroll" |
| | | :scrollY="true" |
| | | @scroll="evt=>onScroll(evt)" |
| | | @touchstart="evt=>onTouch(evt)" |
| | | @touchmove="evt=>onTouch(evt)" |
| | | @touchend="evt=>onTouch(evt)" |
| | | > |
| | | <view |
| | | class="c-infinite-top" |
| | | :class="touching?'touching':''" |
| | | :style="{height: touch.driftTop+'rem'}" |
| | | > |
| | | <view class="inner"> |
| | | <view v-if="touch.dargState===2"> |
| | | <AtActivityIndicator /> |
| | | <text class="text">重新加载中...</text> |
| | | </view> |
| | | <view |
| | | class="tips" |
| | | v-else |
| | | :class="touch.dargState===0?'':'release'" |
| | | > |
| | | <view class="at-icon at-icon-arrow-down"></view> |
| | | <text class="text">下拉刷新</text> |
| | | <text class="text">释放刷新</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <slot /> |
| | | <view class="c-infinite-bottom"> |
| | | <view |
| | |
| | | AtActivityIndicator, |
| | | }, |
| | | props: { |
| | | // 是否自动初始化(自动加载第一页) |
| | | autoInit: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | // 加载页面回调 |
| | | onLoadMore: Function, |
| | | }, |
| | | data() { |
| | | return { |
| | | // 初始化状态 |
| | | inital: false, |
| | | // 当前页面 |
| | | current: 0, |
| | | // 总共页面 |
| | | pageTotal: 1, |
| | | // 加载中状态 |
| | | loading: false, |
| | | // 是否结束状态 |
| | | ending: false, |
| | | // 上次滚动位置 |
| | | lastScrollTop: 0, |
| | | // 滚动节流器 |
| | | scrollTimer: 0, |
| | | // 是否已滚动 |
| | | scrolled: false, |
| | | // 滑屏数据 |
| | | touch: { |
| | | startX: 0, |
| | | startY: 0, |
| | | lastY: 0, |
| | | dargState: 0, |
| | | driftTop: 0, |
| | | }, |
| | | // 正在滑屏状态 |
| | | touching: false, |
| | | }; |
| | | }, |
| | | methods: { |
| | |
| | | current: this.current, |
| | | next: this.current + 1, |
| | | // 加载成功 |
| | | success: (options) => { |
| | | success: options => { |
| | | setTimeout(() => { |
| | | this.loading = false; |
| | | // 没有数据 |
| | |
| | | this.ending = true; |
| | | } |
| | | } |
| | | // 还原下拉 |
| | | if (this.touch.dargState === 2) { |
| | | this.touch.driftTop = 0; |
| | | setTimeout(() => { |
| | | this.touch.dargState = 0; |
| | | }, 300); |
| | | } |
| | | }, 100); |
| | | }, |
| | | // 加载失败 |
| | | fail: () => { |
| | | this.loading = false; |
| | | // 还原下拉 |
| | | if (this.touch.dargState === 2) { |
| | | this.touch.driftTop = 0; |
| | | setTimeout(() => { |
| | | this.touch.dargState = 0; |
| | | }, 300); |
| | | } |
| | | }, |
| | | }); |
| | | }, |
| | | onScroll(evt) { |
| | | // 已经滚动(滚动后禁止下拉刷新) |
| | | this.scrolled = true; |
| | | // 往上 |
| | | if (this.lastScrollTop >= evt.detail.scrollTop) { |
| | | this.lastScrollTop = evt.detail.scrollTop; |
| | |
| | | } |
| | | } |
| | | }, |
| | | // 初始加载 |
| | | initScroll() { |
| | | // 已初始化,跳过 |
| | | if (this.inital) { |
| | |
| | | } |
| | | this.hanldeLoadMore(); |
| | | }, |
| | | // 手指拨动 |
| | | onTouch(evt) { |
| | | // 拉动长度(少于这个值的时候下拉但是不刷新) |
| | | const deviationY = 50; |
| | | // 拉动的最大高度 |
| | | const maxTransY = 100; |
| | | // 按下 |
| | | if (evt.type === 'touchstart') { |
| | | this.touching = true; |
| | | // 手指按下,重置是否已滚动 |
| | | this.scrolled = false; |
| | | if (evt.touches.length !== 1) { |
| | | return; |
| | | } |
| | | this.touch.startX = evt.touches[0].clientX; |
| | | this.touch.startY = evt.touches[0].clientY; |
| | | this.touch.lastY = evt.touches[0].clientY; |
| | | } |
| | | // 滑动 |
| | | else if (evt.type === 'touchmove') { |
| | | // 已滚动跳过 |
| | | if (this.scrolled) { |
| | | return; |
| | | } |
| | | // 加载中跳过 |
| | | if (this.loading) { |
| | | return; |
| | | } |
| | | this.touching = true; |
| | | // 左右偏移判断(向下拉时,如果左右偏移超过阀值不执行下拉操作) |
| | | const ratio = |
| | | Math.abs(evt.touches[0].clientX - this.touch.startX) / |
| | | Math.abs(evt.touches[0].clientY - this.touch.startY); |
| | | const dragDown = this.touch.lastY - evt.touches[0].clientY < 0; |
| | | this.touch.lastY = evt.touches[0].clientY; |
| | | if (dragDown && ratio > 0.3) { |
| | | return; |
| | | } |
| | | // 拖动距离 |
| | | const deltY = evt.touches[0].clientY - this.touch.startY; |
| | | // 拖动值=拖动距离/拖动倍率,使拖动的时候有粘滞的感觉 |
| | | const transY = Math.min(Math.abs(deltY) / 4, maxTransY); |
| | | if (deltY > 0) { |
| | | this.touch.driftTop = (transY / maxTransY) * 5; |
| | | // 超过阀值,可以刷新 |
| | | if (transY >= deviationY) { |
| | | this.touch.dargState = 1; |
| | | } |
| | | // 小于阀值,不能刷新 |
| | | else { |
| | | this.touch.dargState = 0; |
| | | } |
| | | } else { |
| | | this.touch.driftTop = 0; |
| | | } |
| | | } |
| | | // 松开 |
| | | else if (evt.type === 'touchend') { |
| | | this.touching = false; |
| | | // 已滚动跳过 |
| | | if (this.scrolled) { |
| | | this.touch.driftTop = 0; |
| | | return; |
| | | } |
| | | // 加载中跳过 |
| | | if (this.loading) { |
| | | this.touch.driftTop = 0; |
| | | return; |
| | | } |
| | | // 不刷新 |
| | | if (this.touch.dargState === 0) { |
| | | this.touch.driftTop = 0; |
| | | return; |
| | | } |
| | | // 刷新数据 |
| | | if (this.touch.dargState === 1) { |
| | | this.touch.driftTop = (deviationY / maxTransY) * 5; |
| | | // 重新加载 |
| | | this.touch.dargState = 2; |
| | | this.ending = false; |
| | | this.current = 0; |
| | | this.hanldeLoadMore(); |
| | | } |
| | | } |
| | | }, |
| | | }, |
| | | mounted() { |
| | | // 开启自动初始化 |