uniapp中实现锚点定位滚动效果

一、效果如下:

在这里插入图片描述

二、html模块

<view class="menu-content">
  <!-- 左侧导航区域 -->
  <view class="tab-wrap">
    <view
      :class="['tab', { active: activeTab === index }]"
      v-for="(tab, index) in tabList"
      :key="index"
      @click="changeTab(index)"
    >
      {
   
   { tab }}
    </view>
  </view>
  <!-- 右侧滚动区域 -->
  <scroll-view
    scroll-y
    @scrolltoupper="onScrolltoupper"
    @scroll="onScroll"
    :scroll-top="scrollTop"
  >
    <div class="menu-card" v-for="(item, index) in dataList" :key="index">
      <!-- 你的卡片体 -->
    </div>
  </scroll-view>
</view>

三、数据源

data() {
    
    
  return {
    
    
    // 右侧数据
    dateList: [],
    // tab标签数据
    tabList: ["早餐", "午餐", "晚餐"],
    // 激活的tab
    activeTab: 0,
    // 每个卡片距离顶部的距离
    itemScrollTopArray: [],
    // 滚动高度
    scrollTop: 0,
  };
},

四、方法

methods: {
    
    
  // 数据请求
  getList() {
    
    
    this.http({
    
    
      ...this.$miniapi.dishMenu.getCurMonthDetailDish,
      showLoading: true,
    }).then((res) => {
    
    
      this.dataList = res.data;
      // 获取每个卡片距离顶部的距离
      this.getItemScrollTop();
    });
  },
  // 获取右边菜谱每个tab到顶部的距离
  getItemScrollTop() {
    
    
    this.$nextTick(() => {
    
    
      let selectorQuery = uni.createSelectorQuery().in(this);
      selectorQuery
        // menu-card你的卡片类名
        .selectAll(".menu-card")
        .boundingClientRect((rects) => {
    
    
          // rects就是获取的虚拟dom节点数组,所以判断不为空在执行
          if (this.toolClass.isArrayAndNotEmpty(rects)) {
    
    
            rects.forEach((item, index, array) => {
    
    
              // 这里减去rects[0].top,是以为第一个卡片为参考点
              this.itemScrollTopArray.push(item.top - array[0].top);
            });
          }
        })
        .exec();
    });
  },
  // tab切换处理
  changeTab(index) {
    
    
    // 处理激活索引
    this.activeTab = index;
    // 处滚动距离
    this.scrollTop = this.itemScrollTopArray[index];
  },
  // 由于onScroll滚动到顶部,距离不能精准为0,所以触发触顶事件,手动设置scrollTop为0
  onScrolltoupper() {
    
    
    this.scrolltop = 0;
  },
  // 处理滚动逻辑
  onScroll(e) {
    
    
    // 获取当前滚动距离
    const currentScrollTop = e?.detail?.scrollTop;
    if (!currentScrollTop) return;
    // 由于onScroll滚动到顶部,距离不能精准为0,保留20px的安全距离误差
    const index = this.itemScrollTopArray.findIndex(
      (scrollTop) => scrollTop >= currentScrollTop - 30
    );
    // 处理激活步骤
    this.activeTab = index === -1 ? 0 : index;
  },
},

猜你喜欢

转载自blog.csdn.net/qq_44741577/article/details/142661465