综合办公系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sticky-scroll-data.vue 7.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. <!-- 菜单悬浮的原理: 监听滚动条的位置大于某个值时,控制顶部菜单的显示和隐藏, 用法比sticky复杂, 但APP端可兼容低端机 -->
  2. <template>
  3. <view>
  4. <!-- 菜单 (悬浮,预先隐藏)-->
  5. <me-tabs v-if="isShowSticky" v-model="tabIndex" :fixed="true" :tabs="tabs" @change="tabChange"></me-tabs>
  6. <mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" :up="upOption" @scroll="scroll" @topclick="topClick">
  7. <!--轮播-->
  8. <swiper style="min-height: 300rpx" autoplay="true" interval="3000" duration="300" circular="true">
  9. <swiper-item>
  10. <image style="width: 100%;height: auto;" src="https://www.mescroll.com/img/swiper1.jpg" mode="widthFix"/>
  11. </swiper-item>
  12. <swiper-item>
  13. <image style="width: 100%;height: auto;" src="https://www.mescroll.com/img/swiper2.jpg" mode="widthFix"/>
  14. </swiper-item>
  15. </swiper>
  16. <view class="demo-tip">
  17. <view>列表只初始化一次,切换菜单缓存数据</view>
  18. <view>吸顶通过监听滚动条实现, 比sticky复杂, 但APP端可兼容低端机</view>
  19. </view>
  20. <!-- 菜单 (在mescroll-uni中不能使用fixed,否则iOS滚动时会抖动, 所以需在mescroll-uni之外存在一个一样的菜单) -->
  21. <view id="tabInList">
  22. <me-tabs v-model="tabIndex" :tabs="tabs" @change="tabChange"></me-tabs>
  23. </view>
  24. <!-- 数据列表 -->
  25. <good-list :list="goods"></good-list>
  26. </mescroll-body>
  27. </view>
  28. </template>
  29. <script>
  30. import MescrollMixin from "@/components/mescroll-uni/mescroll-mixins.js";
  31. import {apiSearch} from "@/api/mock.js"
  32. export default {
  33. mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件)
  34. data() {
  35. return {
  36. upOption: {
  37. // 如果用mescroll-uni 则需要onScroll: true, 且需要 @scroll="scroll"; 而mescroll-body最简单只需在onPageScroll处理即可
  38. // onScroll: true // 是否监听滚动事件, 默认false (配置为true时,可@scroll="scroll"获取到滚动条位置和方向)
  39. },
  40. tabs:[
  41. {name:'全部', goods: null, num:1, y:0, curPageLen:0, hasNext:true},
  42. {name:'母婴', goods: null, num:1, y:0, curPageLen:0, hasNext:true},
  43. {name:'图书', goods: null, num:1, y:0, curPageLen:0, hasNext:true}
  44. ],
  45. tabIndex: 0, // 当前菜单下标
  46. preIndex: 0, // 前一个菜单下标
  47. navTop: null, // nav距离到顶部的距离 (如计算不准确,可直接写死某个值)
  48. isShowSticky: false // 是否悬浮
  49. }
  50. },
  51. computed: {
  52. // 列表数据
  53. goods() {
  54. return this.tabs[this.tabIndex].goods
  55. }
  56. },
  57. methods: {
  58. /*下拉刷新的回调 */
  59. downCallback() {
  60. // 这里加载你想下拉刷新的数据, 比如刷新轮播数据
  61. // loadSwiper();
  62. // 下拉刷新的回调,默认重置上拉加载列表为第一页 (自动执行 page.num=1, 再触发upCallback方法 )
  63. this.mescroll.resetUpScroll()
  64. },
  65. /*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
  66. upCallback(page) {
  67. //联网加载数据
  68. if(this.isChangeTab){
  69. this.mescroll.hideUpScroll(); // 切换菜单,不显示mescroll进度, 显示系统进度条
  70. uni.showLoading();
  71. }
  72. let keyword = this.tabs[this.tabIndex].name;
  73. apiSearch(page.num, page.size, keyword).then(curPageData=>{
  74. //联网成功的回调
  75. // 当前tab数据
  76. let curTab = this.tabs[this.tabIndex]
  77. //设置列表数据
  78. if(page.num == 1) curTab.goods = []; //如果是第一页需手动制空列表
  79. curTab.goods=curTab.goods.concat(curPageData); //追加新数据
  80. // 数据渲染完毕再隐藏加载状态 this.$nextTick在iOS真机不触发,需改成setTimeout
  81. // this.$nextTick(()=>{
  82. setTimeout(()=>{
  83. // 需先隐藏加载状态
  84. this.mescroll.endSuccess(curPageData.length);
  85. // 再记录当前页的数据
  86. curTab.num = page.num; // 页码
  87. curTab.curPageLen = curPageData.length; // 当前页长
  88. curTab.hasNext = this.mescroll.optUp.hasNext; // 是否还有下一页
  89. // 设置nav到顶部的距离 (需根据自身的情况获取navTop的值, 这里放到列表数据渲染完毕之后)
  90. // 也可以放到onReady里面,或者菜单顶部的数据(轮播等)加载完毕之后..
  91. if(!this.navTop) this.setNavTop()
  92. // 保持tab悬浮,列表数据显示第一条
  93. if(this.isChangeTab){
  94. this.isChangeTab = false;
  95. uni.hideLoading();
  96. if(this.isShowSticky) this.mescroll.scrollTo(this.navTop, 0)
  97. }
  98. },20)
  99. }).catch(()=>{
  100. //联网失败, 结束加载
  101. this.mescroll.endErr();
  102. })
  103. },
  104. // 设置nav到顶部的距离 (滚动条为0, 菜单顶部的数据加载完毕获取到的navTop数值是最精确的)
  105. setNavTop(){
  106. let view = uni.createSelectorQuery().select('#tabInList');
  107. view.boundingClientRect(data => {
  108. console.log('tabInList基本信息 = ' + JSON.stringify(data));
  109. this.navTop = data.top // 到屏幕顶部的距离
  110. }).exec();
  111. },
  112. // mescroll-uni的滚动事件 (需在up配置onScroll:true才生效)
  113. // 而mescroll-body最简单只需在onPageScroll处理即可
  114. scroll(){
  115. console.log('滚动条位置 = ' + this.mescroll.getScrollTop() + ', navTop = ' + this.navTop);
  116. // 菜单悬浮的原理: 监听滚动条的位置大于某个值时,控制顶部菜单的显示和隐藏
  117. if (this.mescroll.getScrollTop() >= this.navTop) {
  118. this.isShowSticky = true // 显示悬浮菜单
  119. } else {
  120. this.isShowSticky = false // 隐藏悬浮菜单
  121. }
  122. },
  123. // 点击回到顶部按钮时,先隐藏悬浮菜单,避免闪动
  124. topClick(){
  125. this.isShowSticky = false
  126. },
  127. // 切换菜单
  128. tabChange (index) {
  129. // 记录前一个菜单的数据
  130. let preTab = this.tabs[this.preIndex]
  131. preTab.y = this.mescroll.getScrollTop(); // 滚动条位置
  132. this.preIndex = index;
  133. // 当前菜单的数据
  134. let curTab = this.tabs[index]
  135. if (!curTab.goods) {
  136. // 没有初始化,则初始化
  137. this.isChangeTab = true;
  138. this.mescroll.resetUpScroll()
  139. } else{
  140. // 初始化过,则恢复之前的列表数据
  141. this.mescroll.setPageNum(curTab.num + 1); // 恢复当前页码
  142. this.mescroll.endSuccess(curTab.curPageLen, curTab.hasNext); // 恢复是否有下一页或显示空布局
  143. this.$nextTick(()=>{
  144. this.mescroll.scrollTo(curTab.y, 0) // 恢复滚动条的位置
  145. })
  146. }
  147. }
  148. },
  149. // 使用mescroll-body最简单只需在onPageScroll处理即可
  150. onPageScroll(e){
  151. console.log('滚动条位置 = ' + e.scrollTop + ', navTop = ' + this.navTop);
  152. if (e.scrollTop >= this.navTop) {
  153. this.isShowSticky = true // 显示悬浮菜单
  154. } else {
  155. this.isShowSticky = false // 隐藏悬浮菜单
  156. }
  157. }
  158. }
  159. </script>
  160. <style>
  161. .demo-tip{
  162. padding: 18rpx;
  163. font-size: 24rpx;
  164. text-align: center;
  165. }
  166. </style>