岁寒之松柏:小程序如何实现IndexBar

前言

本文主要阐述用小程序的原生API如何实现一个IndexBar,当然本文使用的思路只是笔者想到的方法,如果有更好的方法欢迎在评论区指正。

简单实现

什么是IndexBar

我想大家在开发一定遇到过这种需求

左边是一个类似导航的东西,右边是一个轮动条,需要用户在点击左边导航的时候,右边自动滚动到指定位置,右边滚动条轮动的时候需要左右的导航自动选中标题。总体来说逻辑还是比较简单的。从上述需求也很容易得出实现这个东西总体需要两个核心逻辑

  • 实现点击导航栏 滚动视图自动滚动到指定位置
  • 实现滚动滚条 标题栏自动切换

实现视图根据标题自动滚动

在小程序中实现这个功能我们有两个方法

  • 通过动态设置scroll-view的scroll-into-view 属性
  • 通过获取scroll-view的context 执行如下方法

本项目使用第一种方法实现,第二种方式读者可以自己尝试一下 核心思路如下

  1. 在js代码中设置intoViewIdactive 属性分别控制要跳转的scroll-view子视图和当前激活状态的index按钮 并创建changeActive方法用于实现按钮控制scroll-view
  2. 在wxml中绑定intoViewId 与设置changeActive事件

以下时核心代码

JS核心代码

js 复制代码
Page({

  /**
   * 页面的初始数据
   */
  data: {
    // 用于绑定视图id
    intoViewId:"",
    // 用于设置当前处于激活状态的按钮
    active:0,
    categraylist:[{
      name:"推荐",
    },{
      name:"拿铁",
    },{
      name:"美式",
    },{
      name:"摩卡",
    }],
  },
  
  // 修改当前处于激活状态的导航 并 设置scroll需要进入viewId
  changeActive(e){
    const index = e.currentTarget.dataset.index
    this.setData({
      active:index
    })
    this.setData({
      intoViewId:`id-${index}`
    })
  },
})

wxml代码

html 复制代码
<view class="page">
  <view class="top-bar">
  </view>
  <view class="list">
    <view class="left-warpper">
      <block wx:for="{{categraylist}}" wx:key="name">
         <!--设置点击左边框事件 并把当前点击的索引传入 -->
        <view data-index="{{index}}" bind:tap="changeActive" class="btn {{active == index ? 'active' :'' }}">{{item.name}}</view>
      </block>

    </view>
   <!--scroll-into-view 绑定需要跳转的id  scroll-with-animation 启用动画  -->  
    <scroll-view 
      class="coffee-warpper" 
      scroll-into-view="{{intoViewId}}" 
      scroll-with-animation     
      scroll-y>
      <block wx:for="{{categraylist}}" wx:key="name">
        <!-- 为scroll-view子元素设置id -->
        <view id="id-{{index}}" class="coffee-container">
          <view class="title">{{item.name}}</view>
          <block wx:for="{{item.itemList}}" wx:for-item="itm" wx:key="name">
            <coffee-item item="{{itm}}"></coffee-item>
          </block>
        </view>
      </block>
      <view class="blank"></view>
    </scroll-view>
  </view>
</view>  

实现滚动滚动条 标题栏自动切换

实现这个功能 小程序并没有提供现成api 让我们可以绑定scroll-view上的事件就可以实现对scroll-view的监听虽然确实有一个绑定滚动监听的事件但是并没有满足我们需求,不过我们可以使用其他的API实现对scroll状态的监听 比如wx.createIntersectionObserver 这个API主要用来判断子元素是否进入父元素或者离开父元素,我们可以根据这个机制,实现对父元素中子元素的记录具体思路如下:

  • 初始化一个Set保存子视图id
  • 当事件触发时判断Set是否包含子视图id
    • 如果不包含说明第一次触犯 说明是进入视图 把id加入Set
    • 如果包含说明第二次触犯 说明是离开入视图 把id从Set中删除
  • 遍历Set得到最小的id索引就是当前需要激活的侧边栏id索引

根据上面的思路我们可以只需要在js的代码中添加如下代码就可以实现需要的功能

js 复制代码
   // 用于保存当前在视图中视图id
   let idSet = new Set()
   Page({
    
    onReady() {
    this._observer = wx.createIntersectionObserver(this,{
      observeAll:true
    })
    this._observer
      .relativeTo('.coffee-warpper',{top:1})
      .observe('.coffee-container', (res) => {
         
         if(idSet.has(res.id)){
          // 当前存在的这个VIEWID 
          // 说明scroll-view视图中存在这个子视图 
          // 再次触犯说明这个子视图 离开了scroll-view
          idSet.delete(res.id)
          let ids =  Array.from(idSet).map(item=>{
              return Number(item.replace("id-",""))
          })
          let min = Math.min(...ids)
          this.setData({
            active:min
          })
         }else{
          idSet.add(res.id)
         }
      })
  
  },
   
   })
相关推荐
小高007几秒前
🔥「从零到一」我用 Node BFF 手撸一个 Vue3 SSR 项目(附源码)
前端·javascript·vue.js
SailingCoder2 分钟前
AI 流式对话该怎么做?SSE、fetch、axios 一次讲清楚
前端·javascript·人工智能·ai·node.js
『 时光荏苒 』3 分钟前
微信小程序we分析如何采集webview的体验信息
微信小程序·小程序·webview·we分析
hxjhnct7 分钟前
Vue 实现多行文本“展开收起”
前端·javascript·vue.js
橙子的AI笔记8 分钟前
2025年全球最受欢迎的JS鉴权框架Better Auth,3分钟带你学会
前端·ai编程
百锦再8 分钟前
Vue大屏开发全流程及技术细节详解
前端·javascript·vue.js·微信小程序·小程序·架构·ecmascript
独自破碎E13 分钟前
你知道Spring Boot配置文件的加载优先级吗?
前端·spring boot·后端
一树山茶15 分钟前
Vue变化响应
前端
黑土豆17 分钟前
一次真实的流式踩坑:fetchEventSource vs fetch流读取的本质区别
前端·javascript·ai编程