岁寒之松柏:小程序如何实现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)
         }
      })
  
  },
   
   })
相关推荐
茶茶只知道学习3 分钟前
通过鼠标移动来调整两个盒子的宽度(响应式)
前端·javascript·css
蒟蒻的贤6 分钟前
Web APIs 第二天
开发语言·前端·javascript
清灵xmf10 分钟前
揭开 Vue 3 中大量使用 ref 的隐藏危机
前端·javascript·vue.js·ref
su1ka11115 分钟前
re题(35)BUUCTF-[FlareOn4]IgniteMe
前端
测试界柠檬17 分钟前
面试真题 | web自动化关闭浏览器,quit()和close()的区别
前端·自动化测试·软件测试·功能测试·程序人生·面试·自动化
多多*17 分钟前
OJ在线评测系统 登录页面开发 前端后端联调实现全栈开发
linux·服务器·前端·ubuntu·docker·前端框架
2301_8010741518 分钟前
TypeScript异常处理
前端·javascript·typescript
小阿飞_19 分钟前
报错合计-1
前端
caperxi21 分钟前
前端开发中的防抖与节流
前端·javascript·html
霸气小男21 分钟前
react + antDesign封装图片预览组件(支持多张图片)
前端·react.js