UNPKG

vue-scroll-load-top-bottom

Version:

vue component, scroll to load more contents, surport load top and load bottom

279 lines (262 loc) 8.18 kB
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 | | 手动触发判断内容是否够填充容器