岁寒之松柏:小程序如何实现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)
         }
      })
  
  },
   
   })
相关推荐
喵叔哟25 分钟前
重构代码之取消临时字段
java·前端·重构
还是大剑师兰特1 小时前
D3的竞品有哪些,D3的优势,D3和echarts的对比
前端·javascript·echarts
王解1 小时前
【深度解析】CSS工程化全攻略(1)
前端·css
一只小白菜~1 小时前
web浏览器环境下使用window.open()打开PDF文件不是预览,而是下载文件?
前端·javascript·pdf·windowopen预览pdf
方才coding1 小时前
1小时构建Vue3知识体系之vue的生命周期函数
前端·javascript·vue.js
阿征学IT1 小时前
vue过滤器初步使用
前端·javascript·vue.js
王哲晓1 小时前
第四十五章 Vue之Vuex模块化创建(module)
前端·javascript·vue.js
丶21361 小时前
【WEB】深入理解 CORS(跨域资源共享):原理、配置与常见问题
前端·架构·web
发现你走远了1 小时前
『VUE』25. 组件事件与v-model(详细图文注释)
前端·javascript·vue.js
Mr.咕咕1 小时前
Django 搭建数据管理web——商品管理
前端·python·django