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"
  >
    <view style="content: ''; overflow: hidden"></view>
    <div class="menu-card" v-for="(item, index) in dataList" :key="index">
      <!-- 你的卡片体 -->
    </div>
    <view style="content: ''; overflow: hidden"></view>
  </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;
  },
},
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值