0.1.1 • Published 6 years ago

vue-scroll-load-top-bottom v0.1.1

Weekly downloads
8
License
MIT
Repository
github
Last release
6 years ago

vue-scroll-load-top-bottom

vue组件 支持向上和向下滚动加载


使用方法 npm install vue-scroll-load-top-bottom

代码样例 App.vue

<template>
  <div class="wrapper">
    <div ref="pageContainer" class="pr l_0 t_0 w_p100 h_p100 dfx  flex_direction_column">
      <div class="dfx pr w_p100 minh_400" v-show="showSection1">
        <span>内容1 <button @click="hideSection1">隐藏此区块</button></span>
      </div>
      <div id="scrollerWrapper" ref="scrollerWrapper" class="flex1 w_p100 pr ovh ovy_scroll">
        <vue-scroll-load-top-bottom 
          ref="scroller" 
          id="scroller"
          class=""
          :wrapper="$refs.scrollerWrapper"
          :load-bottom-disabled="loadBottomDisabled" 
          :load-top-disabled="loadTopDisabled"
          @on-load-top="onLoadTop"
          @on-load-bottom="onLoadBottom">
          <div class="dfx pr w_p100 ta_c line_height_2 bs_border transition_height ovh" slot="loadTop" :class="{ h_70: isLoadingTopData, h_0: !isLoadingTopData }">
            <p>加载中</p>
          </div>
          <div class="pr">
            <div v-for="(item, index) in list" :key="index" class="item">Page: {{ item.page }}  Index: {{ index }}</div>
          </div>
          <div class="dfx w_p100 ta_c line_height_2 bs_border transition_height ovh" slot="loadBottom" :class="{ h_70: isLoadingBottomData, h_0: !isLoadingBottomData }">
            <p>加载中···</p>
          </div>
        </vue-scroll-load-top-bottom>
      </div>
      <div class="dfx pr w_p100 minh_400" v-show="showSection2">
        <span>内容2 <button @click="hideSection2">隐藏此区块</button></span>
      </div>
    </div>
  </div>
</template>

<script>
import vueScrollLoadTopBottom from 'vue-scroll-load-top-bottom';

export default {
  data() {
    return {
      init: false,
      list: [],
      prevPageNo: 3,
      pageNo: 4,
      nextPageNo: 5,
      pageContainer: null,
      pageInited: false,
      loadTopDisabled: true,
      loadBottomDisabled: false,
      isLoadingTopData: false,
      isLoadingBottomData: false,
      showSection1: true,
      showSection2: false,
    };
  },
  components: {
    vueScrollLoadTopBottom,
  },
  mounted() {
    this.pageContainer = this.$refs.pageContainer;
    this.scroller = this.$refs.scroller;
    this.pageInited = true;
  },
  methods: {
    hideSection1() {
      this.showSection1 = false;
      this.$nextTick(() => {
        this.scroller.checkInitContentIsEnough();
      });
    },
    hideSection2() {
      this.showSection2 = false;
      this.$nextTick(() => {
        this.scroller.checkInitContentIsEnough();
      });
    },
    makeList() {
      const arr = [];
      for (let i = 0; i < 2; i += 1) {
        // eslint-disable-next-line
        arr.push({ page: this.pageNo });
      }
      return arr;
    },
    onLoadBottom() {
      console.log('onLoadBottom 执行了');
      if (this.nextPageNo > 10) {
        this.loadBottomDisabled = true;
        this.showSection2 = true;
        return false;
      }
      this.isLoadingBottomData = true;
      setTimeout(() => {
        this.pageNo = this.init ? this.nextPageNo : this.pageNo;
        this.list = this.list.concat(this.makeList());
        if (this.init) {
          this.nextPageNo += 1;
        }
        this.$refs.scroller.releaseBottomLock();
        this.isLoadingBottomData = false;
        this.init = true;
      }, 15e2);
      return true;
    },
    onLoadTop() {
      console.log('onLoadTop 执行了');
      if (this.prevPageNo < 1) {
        this.loadTopDisabled = true;
        this.showSection1 = true;
        this.pageContainer.scrollTop = this.scroller.heightSubtract +
          Math.abs(this.scroller.bcr.top);
        this.$refs.scroller.releaseTopLock();
        return false;
      }
      this.isLoadingTopData = true;
      setTimeout(() => {
        this.pageNo = this.prevPageNo;
        this.list = this.makeList().concat(this.list);
        this.prevPageNo -= 1;
        this.isLoadingTopData = false;
        this.$refs.scroller.releaseTopLock();
        this.$nextTick(() => {
          /* eslint-disbale no-mixed-operators */
          this.$refs.scrollerWrapper.scrollTop = this.scroller.heightSubtract +
            Math.abs(this.scroller.bcr.top) - this.scroller.wrapperOffsetTop;
        });
      }, 15e2);
      return true;
    },
  },
};
</script>

<style scoped>
.pr {
  position: relative;
}
.pa {
  position: absolute;
}
.l_0 {
  left: 0;
}
.t_0 {
  top: 0;
}
.dfx {
  display: flex;
  align-items: center;
  justify-content: center;
}
.flex1 {
  flex: 1 0;
}
.flex_direction_column {
  flex-direction: column;
}
.minh_400 {
  min-height: 10rem;
}
.h_0 {
  height: 0;
}
.h_60 {
  height: 1.5rem;
}
.h_70 {
  height: 1.75rem;
}
.bc_red {
  background-color: red;
}
.bc_blue {
  background-color: blue;
}
.ta_c {
  text-align: center;
}
.line_height_2 {
  line-height: 2;
}
.w_p100 {
  width: 100%;
}
.h_p100 {
  height: 100%;
}
.ovh {
  overflow: hidden;
}
.ovy_scroll {
  overflow-y: scroll;
}

.item {
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
}
.item:nth-of-type(2n) {
  background-color: red;
  height: 5rem;
}
.item:nth-of-type(2n+1) {
  background-color: blue;
  height: 9rem;
}
.transition_height {
  transition: height ease-in-out;
}
.transition_duration_300 {
  transition-duration: 300ms;
}
/*  */
.wrapper {
  position: fixed;
  left: 50%;
  top: 0;
  transform: translate3d(-50%, 0, 0);
  height: 100%;
  width: 400px;
  background-color: #f3f3f3;
}
button {
  display: inline-block;
  appearance: none;
  border: 1px solid #ddd;
  padding:  3px 10px;
  border-radius: 4px;
}
</style>

props: | propValue | required | default | description | :--------: | :-----: | :----: | :----: | | wrapper | false | null | 组件父级overflow-y:scroll的dom元素。当父级容器不是为全屏并且设置了高度时会用到 | delay | false | 200(ms) | 检测组件状态的时间间隔 | loadTopDisabled | false | true | 禁止向上加载。当 loadTopDisabled 和 loadBottomDisabled 都为false时会取消监听 | loadBottomDisabled | false | false | 禁止向下加载。当 loadTopDisabled 和 loadBottomDisabled 都为false时会取消监听 | topDistance| false | 100 | 向上加载触发距离 | bottomDistance | false | 200 | 向下加载触发距离 | touchThreshold | false | 40 | 触摸阈值 | loadAuto | false | true | 当内容不够时是否自动触发loadBottom


events: | eventName | params | description | :-------: | :-----: | :----: | | on-content-is-not-enough | | 内容不够时触发 | on-load-top | | 向上加载时触发。会锁定向上加载状态。需手动releaseTopLock() | on-load-bottom | | 向下加载时触发。会锁定向下加载状态。需手动releaseBottomLock()


other events: | eventName | params | description | :-------: | :-----: | :----: | | releaseTopLock | | 释放向上加载的锁 | releaseBottomLock | | 释放向下加载的锁 | checkInitContentIsEnough | | 手动触发判断内容是否够填充容器

0.1.1

6 years ago

0.1.0

6 years ago

0.0.9

6 years ago

0.0.8

6 years ago

0.0.7

6 years ago

0.0.6

6 years ago

0.0.5

6 years ago

0.0.4

6 years ago

0.0.3

6 years ago

0.0.2

6 years ago

0.0.1

6 years ago