岁寒之松柏:小程序如何实现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)
         }
      })
  
  },
   
   })
相关推荐
滚雪球~27 分钟前
npm error code ETIMEDOUT
前端·npm·node.js
沙漏无语29 分钟前
npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js
supermapsupport31 分钟前
iClient3D for Cesium在Vue中快速实现场景卷帘
前端·vue.js·3d·cesium·supermap
brrdg_sefg32 分钟前
WEB 漏洞 - 文件包含漏洞深度解析
前端·网络·安全
胡西风_foxww39 分钟前
【es6复习笔记】rest参数(7)
前端·笔记·es6·参数·rest
m0_7482548840 分钟前
vue+elementui实现下拉表格多选+搜索+分页+回显+全选2.0
前端·vue.js·elementui
YUJIAN。1 小时前
使用uniapp开发微信小程序-框架搭建
微信小程序·小程序·uni-app
星就前端叭1 小时前
【开源】一款基于Vue3 + WebRTC + Node + SRS + FFmpeg搭建的直播间项目
前端·后端·开源·webrtc
m0_748234522 小时前
前端Vue3字体优化三部曲(webFont、font-spider、spa-font-spider-webpack-plugin)
前端·webpack·node.js
Web阿成2 小时前
3.学习webpack配置 尝试打包ts文件
前端·学习·webpack·typescript