小程序锚点定位+页面滑动tab跟随

3,148 阅读2分钟

效果:(图片有点模糊将就看)

图像.GIF

1、小程序实现锚点定位

方案采用小程序 scroll-view 标签,设置该标签的 scroll-into-view属性;

// 示例:
// tab-box 自己实现
<tab-box active="activeIndex" bindClick="setActive"></tab-box>

// 注意:scroll-view 必须要有高度设置
<scroll-view style="height:500rpx;" scroll-into-view="{{toView}}">
    <view id="v1"></view>
    <view id="v2"></view>
    <view id="v3"></view>
    <!-- ...更多 -->
</scroll-view>


// js部分
setActive(e){
    const { refId, index } = e.detail;
    this.setData({
        toView: refId,  // refId 值为 v1,v2,v3等
        activeIndex: index  // index 为当前点击tab的下标
    }
}

2、页面滑动Tab跟随

此部分方案,我们依然采用 scroll-view 标签,因为实现的效果是 1+2,所以对于第2部分我们的实现要更复杂!

  • 需求: gif图这里需求是搜索功能,必然数据是动态的(即某个tab对应的模块可能无数据,或者某个模块的列表有1个、2个之分);这种情况下实现根据页面的滑动做tab跟随!

  • 原理: 根据scroll-view提供的滚动距离,判断模块的滚动位置,到达视图scroll-view的顶端时设置当前tab-box所对应的activeIndex;

  • 实现:

// wxml部分
// scroller中的元素距顶部位置,真机初次渲染为负值 与 开发者工具模拟器正值 表现不一致 
// 为了获取到正值,恶心的东西,只能这么费劲的搞了
<scroll-view wx:if="{{isInit}}" id="scroller" class="scroller" style="height:{{scrollHei}}px;" scroll-anchoring="true" enable-passive="true" show-scrollbar="{{false}}" scroll-with-animation="{{true}}" scroll-y="true" bindscroll="scroll" scroll-into-view="{{toView}}">
    <template is="content" data="你需要传给展示内容的数据"></template>
</scroll-view>

<view wx:else class="scroller" id="scroller" style="height:{{scrollHei}}px;">
    <template is="content" data="你需要传给展示内容的数据"></template>
</view>

<template name="content">
    <!-- ...内容模板,接收上述template的数据进行展示渲染 -->
</template>

// js 滚动设置部分
Page({
    scrollTops: [],  // 存储各个模块距scroller顶部的距离
    data: {
        isInit: false, // 是否已进行初始化,即获取到正确的scrollTops
        scrollHei: 0, // scroller的高度
    },
    
    scroll(e){
        const scrollTop = e.detail.scrollTop;
        const len = this.scrollTops.length;
        let setIndex;

        for (let i = 0, cur, next; i < len; i++) {
            cur = this.scrollTops[i];
            next = this.scrollTops[i + 1];
            if (scrollTop < this.scrollTops[0]) {
                setIndex = 0;
                break;
            } else if (scrollTop >= cur && scrollTop < next) {
                setIndex = i;
                break;
            } else if (scrollTop >= this.scrollTops[len - 1]) {
                setIndex = len - 1;
                break;
            }
        }
        if (setIndex != this.data.navIndex) {
            this.setData({
                activeIndex: setIndex,
            });
        }
    }
})

3、完整代码

因为篇幅原因,完整叙述实在是麻烦!

示例代码见小程序代码片段

示例代码中未实现下拉刷新上拉加载;后续有时间再补充~

吐槽:想参加码上掘金的活动,奈何跑不了小程序代码;算了吧,当成自己的记录分享给能用到的朋友们。 欢迎点赞!