当前位置:   article > 正文

uniapp实现仿京东左右联动活动(商品分类)_uniapp实现左右滑动的商品列表页并实时请求数据

uniapp实现左右滑动的商品列表页并实时请求数据

第一步,页面布局

  1. <view class="u-wrap">
  2. <view class="u-menu-wrap">
  3. <scroll-view scroll-y scroll-with-animation class="u-tab-view menu-scroll-view" :scroll-top="scrollTop" :scroll-into-view="itemId">
  4. <view v-for="(item,index) in flist" :key="index" class="u-tab-item" :class="[current == index ? 'u-tab-item-active':'']" @tap.stop="swichMenu(index)">
  5. <text class="u-line-1">{{item.name}}</text>
  6. </view>
  7. </scroll-view>
  8. <scroll-view scroll-y scroll-with-animation :scroll-top="scrollRightTop" class="right-box" @scroll="rightScroll">
  9. <view class="page-view">
  10. <view class="class-item" :id="'item' + index" v-for="(item,index) in slist" :key="index">
  11. <view class="item-title">
  12. <text>{{item.name}}</text>
  13. </view>
  14. <view class="item-container">
  15. <view class="thumb-box" v-for="(item1,index1) in item.children" :key="index1" @click="featureC(item1.id)">
  16. <image :src="item1.img_url" class="item-menu-image" mode=""></image>
  17. <view class="item-menu-name">{{item1.name}}</view>
  18. </view>
  19. </view>
  20. </view>
  21. </view>
  22. </scroll-view>
  23. </view>
  24. </view>

第二步:css部分,这里就自己写了,按照自己的项目效果图自己调一下效果

第三步:js部分

1、

  1. data() {
  2. return {
  3. scrollTop: 0, //tab标题的滚动条位置
  4. oldScrollTop: 0, // tab标题的滚动条旧位置
  5. current: 0, // 预设当前项的值
  6. menuHeight: 0, // 左边菜单的高度
  7. menuItemHeight: 0, // 左边菜单item的高度
  8. itemId: '', // 栏目右边scroll-view用于滚动的id
  9. scrollRightTop: 0, // 右边栏目scroll-view的滚动条高度
  10. arr: [], // 储存距离顶部高度的数组
  11. timer: null, // 定时器
  12. flist: [], //左侧一级分类
  13. slist: [] //右侧一级+二级分类,构造可以嵌套的数组结构
  14. }
  15. },

2、点击左侧分类事件

  1. /**
  2. * 点击左边的栏目切换
  3. * @index 传入的 ID
  4. */
  5. async swichMenu(index) {
  6. if(this.arr.length == 0) {
  7. await this.getMenuItemTop();
  8. }
  9. if (index == this.current) return;
  10. this.scrollRightTop = this.oldScrollTop;
  11. this.$nextTick(function(){
  12. this.scrollRightTop = this.arr[index];
  13. this.current = index;
  14. this.leftMenuStatus(index);
  15. })
  16. },

3、右侧滑动事件

 

  1. async rightScroll(e) {
  2. this.oldScrollTop = e.detail.scrollTop;
  3. if(this.arr.length == 0) {
  4. await this.getMenuItemTop();
  5. }
  6. if(this.timer) return ;
  7. if(!this.menuHeight) {
  8. await this.getElRect('menu-scroll-view', 'menuHeight');
  9. }
  10. setTimeout(() => { // 节流
  11. this.timer = null;
  12. // scrollHeight为右边菜单垂直中点位置
  13. // let scrollHeight = e.detail.scrollTop + this.menuHeight / 2;
  14. // scrollHeight为右边菜单头部位置
  15. let scrollHeight = e.detail.scrollTop + 20;
  16. for (let i = 0; i < this.arr.length; i++) {
  17. let height1 = this.arr[i];
  18. let height2 = this.arr[i + 1];
  19. if (!height2 || scrollHeight >= height1 && scrollHeight < height2) {
  20. this.leftMenuStatus(i);
  21. return ;
  22. }
  23. }
  24. }, 10)
  25. },

4、页面初始化时,获取右边每个节点距离顶部的高度,主要用于判断是否滑动,比如右边数据比较少的时候就不会在滑动

  1. onReady() {
  2. this.getMenuItemTop()
  3. },
  4. getMenuItemTop() {
  5. new Promise(resolve => {
  6. let selectorQuery = uni.createSelectorQuery();
  7. selectorQuery.selectAll('.class-item').boundingClientRect((rects) => {
  8. // 如果节点尚未生成,rects值为[](因为用selectAll,所以返回的是数组),循环调用执行
  9. if(!rects.length) {
  10. setTimeout(() => {
  11. this.getMenuItemTop();
  12. }, 10);
  13. return ;
  14. }
  15. rects.forEach((rect) => {
  16. // 视情况而定,这里减去rects[0].top,是因为第一项顶部可能不是贴到导航栏(比如有个搜索框的情况)
  17. // this.arr.push(rect.top - rects[0].top);
  18. this.arr.push(rect.top)
  19. resolve();
  20. })
  21. }).exec()
  22. })
  23. },

5、基础功能函数

  1. /**
  2. * 观测元素相交状态
  3. * 检测右边scroll-view的id为itemxx的元素与right-box的相交状态
  4. * 如果跟.right-box底部相交,就动态设置左边栏目的活动状态
  5. */
  6. async observer() {
  7. this.tabbar.map((val, index) => {
  8. let observer = uni.createIntersectionObserver(this);
  9. observer.relativeTo('.right-box', {
  10. top: 0
  11. }).observe('#item' + index, res => {
  12. if (res.intersectionRatio > 0) {
  13. let id = res.id.substring(4);
  14. this.leftMenuStatus(id);
  15. }
  16. })
  17. })
  18. },
  19. /**
  20. * 设置左边菜单的滚动状态
  21. * @index 传入的 ID
  22. */
  23. async leftMenuStatus(index) {
  24. this.current = index;
  25. // 如果为0,意味着尚未初始化
  26. if (this.menuHeight == 0 || this.menuItemHeight == 0) {
  27. await this.getElRect('menu-scroll-view', 'menuHeight');
  28. await this.getElRect('u-tab-item', 'menuItemHeight');
  29. }
  30. // 将菜单活动item垂直居中
  31. this.scrollTop = index * this.menuItemHeight + this.menuItemHeight / 2 - this.menuHeight / 2;
  32. },
  33. /**
  34. * 获取一个目标元素的高度
  35. * @elClass 元素的类名
  36. * @dataVal 储存高度的对象
  37. */
  38. getElRect(elClass, dataVal) {
  39. new Promise((resolve, reject) => {
  40. const query = uni.createSelectorQuery().in(this);
  41. query.select('.' + elClass).fields({
  42. size: true
  43. }, res => {
  44. // 如果节点尚未生成,res值为null,循环调用执行
  45. if (!res) {
  46. setTimeout(() => {
  47. this.getElRect(elClass);
  48. }, 10);
  49. return;
  50. }
  51. this[dataVal] = res.height;
  52. resolve();
  53. }).exec();
  54. })
  55. },

主要是uniapp操作dom节点的时候不是很方便,核心的实现原理其实跟jq一样 

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/779422
推荐阅读
相关标签
  

闽ICP备14008679号