uniapp 实现tabbar分类导航及滚动联动效果
思路:使用两个scroll-view,tabbar分类导航使用scrollleft移动,内容联动使用页面滚动onPageScroll监听滚动高度
效果图

<template><view class="content" ><view :class="[isSticky ? 'tab-sticky': '']"><view class="base-combox" ><uni-icons type="location-filled" color="#85D8CE" size="25" /><text class="tag-text">{{base[0].name}}</text></view><view class="u-tab" :class="[!isSticky ? 'tab-sticky': '']"><scroll-view scroll-x="true" scroll-with-animation="true" class="u-tab-view menu-scroll-view" :scroll-left="scrollLeft"><view v-for="(item,index) in tabbar" :key="index" class="u-tab-item" :class="[isActive == index ? 'u-tab-item-active' : '']"@tap.stop="swichMenu(index)"><view class="u-line-1">{{item.name}}</view></view></scroll-view></view></view><scroll-view :scroll-top="scrollTop" scroll-y scroll-with-animation class="right-box" @scroll="upScroll"><view class="page-view"><view class="class-item" :id="'item' + index" v-for="(item , index) in tabbar" :key="index"><view class="item-title"><text>{{item.name}}</text></view><view class="item-container"><view class="thumb-box" v-for="(item1, index1) in item.children" :key="index1" @tap="goList(item1)"><image v-if="item1.icon != ''" class="item-menu-image" :src="item1.icon" mode=""></image><view v-else class="item-menu-image row-c" style="background-color: #F4F6F8;"><text style="font-size: 20rpx;color: #d0d0d0;">加载失败</text></view><view class="item-menu-name">{{item1.name}}</view></view></view></view></view></scroll-view></view>
</template><script>export default {components: {},data() {return {moduleData: [],base:[{name:"请选择地点",id:'0'}],showType:'horizontally', //vertically,horizontallymenuIcon:'../../static/list_h.png',//../../static/list_v.pngtabbar: [],isActive : 0,scrollLeft: 0, // 横向滚动条位置scrollTop: 0,baseComboxH: 0, // 地址区的高度tabbarScrollW: 0, // 导航区宽度tabbarScrollH: 0, // 导航区高度isSticky: true, // 是否吸顶timer: null // 定时器}},onLoad(option) {this.tabbar = [{id:1,name:"菜单一",children:[{id:11,name:"子菜单一"},{id:12,name:"子菜单二"}]},{id:2,name:"菜单二",children:[{id:11,name:"子菜单一子菜单一子菜单一子菜单一",icon:"/static/bq2.png"},{id:12,name:"子菜单二"},{id:13,name:"子菜单三"},{id:14,name:"子菜单四"},{id:15,name:"子菜单五"},{id:16,name:"子菜单六"}]},{id:3,name:"菜单三",children:[{id:21,name:"子菜单一"},{id:22,name:"子菜单二"}]},{id:3,name:"菜单四",children:[{id:31,name:"子菜单一"},{id:32,name:"子菜单二"}]},{id:5,name:"菜单五",children:[{id:41,name:"子菜单一"},{id:42,name:"子菜单二"}]},{id:6,name:"菜单六",children:[{id:51,name:"子菜单一"},{id:52,name:"子菜单二"}]}]},onReady() {},mounted(){this.getScrollW();},onPageScroll(e){//console.log(e,e.scrollTop)if(this.timer){clearTimeout(this.timer)}this.timer = setTimeout(() => { // 节流this.timer = null;// scrollHeight为右边菜单垂直中点位置// let scrollHeight = e.detail.scrollTop + this.menuHeight / 2;// scrollHeight为右边菜单头部位置let scrollHeight = e.scrollTop + this.tabbarScrollH + this.baseComboxH + 26;let len = this.tabbar.lengthfor (let i = 0; i < len-1; i++) {let height1 = this.tabbar[i].top;let height2 = this.tabbar[i + 1].top;// console.log(height2,scrollHeight,height1)if (scrollHeight >= height1 && scrollHeight < height2) {this.tabbarStatus(i);return ;}}if(scrollHeight >= this.tabbar[len-1].top){this.tabbarStatus(len-1);return ;}}, 10)},methods: {goList(value) {var item = {title:value.title,labelName:value.labelName}uni.navigateTo({url:value.url+'?item='+encodeURIComponent(JSON.stringify(item))})},/*** 点击上方的tab切换* @index 传入的 ID*/async swichMenu(index) {if (index == this.isActive ) return;//this.scrollLeft = 0;this.$nextTick(function(){//for (let i = 0; i < index - 1; i++) {//this.scrollLeft += this.tabbar[i].width//};// this.isActive = index;// // 效果三(当前点击子元素居中展示) 不受子元素宽度影响// this.scrollLeft = this.tabbar[index].left - this.tabbarScrollW / 2 + this.tabbar[index].width / 2;this.tabbarStatus(index);//this.scrollTop = this.tabbar[index].topuni.pageScrollTo({duration:200, // 毫秒scrollTop: (this.tabbar[index].top - this.tabbarScrollH - this.baseComboxH - 18) // 位置});// console.log(this.scrollLeft,this.scrollTop)})},// 获取标题区域宽度,和每个子元素节点的宽度以及元素距离左边栏的距离getScrollW() {const query = uni.createSelectorQuery().in(this);query.select('.u-tab-view').boundingClientRect(data => {// 拿到 scroll-view 组件宽度高度this.tabbarScrollW = data.widththis.tabbarScrollH = data.height}).exec();query.select('.base-combox').boundingClientRect(data => {// 拿到 base-combox 高度this.baseComboxH = data.height}).exec();query.selectAll('.u-tab-item').boundingClientRect(data => {let dataLen = data.length;for (let i = 0; i < dataLen; i++) {// scroll-view 子元素组件距离左边栏的距离this.tabbar[i].left = data[i].left;// scroll-view 子元素组件宽度this.tabbar[i].width = data[i].width}}).exec();query.selectAll('.class-item').boundingClientRect(data => {let dataLen = data.length;for (let i = 0; i < dataLen; i++) {// scroll-view 子元素组件距离上边栏的距离this.tabbar[i].top = data[i].top;}}).exec()},upScroll(e){if(e.detail.scrollTop>50){this.isSticky = true}else{this.isSticky = false}console.log(e.detail.scrollTop)},/*** 设置上方菜单的滚动状态* @index 传入的 ID*/async tabbarStatus(index) {this.isActive = index;// 效果三(当前点击子元素居中展示) 不受子元素宽度影响this.scrollLeft = this.tabbar[index].left - this.tabbarScrollW / 2 + this.tabbar[index].width / 2;}}}
</script><style scoped>page{background-color: #fafafa !important;display: block;/* overflow: hidden; */}.content {min-height: 100vh;display: flex;flex-direction: column;}.base-combox{align-items: center;justify-content: center;height: 50rpx;}.u-tab-item-active {position: relative;color: #000;font-size: 16px;font-weight: 600;}.u-tab-item-active::after {content: ''; // 必须display: block;width: 30px;height: 4px;background-color: #000;margin: 0 auto;border-radius: 10px;}.u-tab{border-bottom: 1rpx solid #f2f2f2;background-color: #ffffff;z-index: 99;width: 100%;align-items: center;height: 100rpx;margin-top: 10px;}.u-tab-view{box-sizing: border-box;padding-left: 30rpx;padding-right: 30rpx;width: 100%;white-space: nowrap;}.u-tab-item{display: inline-block;box-sizing: border-box;line-height: 60rpx;margin-right: 35rpx;font-size: 16px;padding-top: 10px;},.u-line-1{padding-bottom: 7px;}/* 隐藏scroll-view滚动条 *//deep/::-webkit-scrollbar{display: none;}uni-scroll-view .uni-scroll-view::-webkit-scrollbar {display: none}.right-box{/* height: 100vh; */}.page-view {padding: 16rpx;flex-direction: column;}.class-item {display: block;margin-bottom: 30rpx;background-color: #fff;padding: 16rpx;border-radius: 8rpx;}.class-item:last-child {min-height: calc(100vh - 102rpx - 50rpx - 20rpx - 88rpx - 32rpx - 64rpx );}.item-title {font-size: 26rpx;color: $u-main-color; font-weight: bold;}.item-menu-name {margin-top: 8rpx;font-weight: normal;font-size: 24rpx;color: $u-main-color;}.item-container {display: flex;flex-wrap: wrap;}.thumb-box {width: 25%;display: flex;align-items: center;justify-content: center;flex-direction: column;margin-top: 20rpx;}.item-menu-image {width: 60rpx;height: 60rpx;}.tab-sticky{display: flex;flex-direction: column;position: -webkit-sticky;position: sticky;top: var(--window-top);z-index: 99;background-color: #fff;}</style>相关文章:
uniapp 实现tabbar分类导航及滚动联动效果
思路:使用两个scroll-view,tabbar分类导航使用scrollleft移动,内容联动使用页面滚动onPageScroll监听滚动高度 效果图 <template><view class"content" ><view :class"[isSticky ? tab-sticky: ]">…...
华为数字化转型的本质为何是管理变革
随着全球经济的加速数字化转型,企业纷纷进入了数字化时代的大潮。华为作为数字化转型的领军者,已经成功实践了从传统企业向数字化企业的蜕变。对于企业而言,数字化转型不仅仅是新技术的应用,更是一场管理变革。在这场变革的背后&a…...
【数据库】深入解析慢 SQL 的识别与优化策略
文章目录 什么是慢 SQL?慢 SQL 的危害如何检测分析慢 SQL使用 MySQL 慢查询日志利用 EXPLAIN 分析执行计划通过 Profiling 获取详细执行信息借助慢 SQL 收集分析平台 实际案例解析:600秒的慢 SQL 优化之旅问题描述初步分析优化步骤1. 优化 SQL 语句结构2…...
Linux从入门到精通
远程连接linux操作系统 Linux的图形化界面并不稳定,因此往往使用命令行去接触Linux操作系统 远程连接到Linux操作系统需要借助一个叫做finalshell的软件,官方地址如下: finalshell官方下载 在linux的terminal终端中输入指令 ifconfig就可以…...
代码随想录算法训练营第四十四天|Day44 动态规划
1143.最长公共子序列 视频讲解:https://www.bilibili.com/video/BV1ye4y1L7CQ https://programmercarl.com/1143.%E6%9C%80%E9%95%BF%E5%85%AC%E5%85%B1%E5%AD%90%E5%BA%8F%E5%88%97.html 思路 #define max(a, b) ((a) > (b) ? (a) : (b)) int longestCommonSu…...
C++初阶——优先队列
一、什么是优先队列 优先队列是一个容器适配器,存储于优先队列中的元素按照某种优先级自动排序。优先队列类似于堆,元素可以随时插入,但是只能弹出优先级最高的元素。默认是一个大根堆,也就是元素越大,优先级越高。 二…...
10月月报 | Apache DolphinScheduler进展总结
各位热爱 Apache DolphinScheduler 的小伙伴们,社区10月份月报更新啦!这里将记录 DolphinScheduler 社区每月的重要更新,欢迎关注! 月度Merge之星 感谢以下小伙伴10月份为 Apache DolphinScheduler 所做的精彩贡献(排…...
WSL--无需安装虚拟机和docker可以直接在Windows操作系统上使用Linux操作系统
安装WSL命令 管理员打开PowerShell或Windows命令提示符,输入wsl --install,然后回车 注意:此命令将启用运行 WSL 和安装 Linux 的 Ubuntu 发行版所需的功能。 注意:默认安装最新的Ubuntu发行版。 注意:默认安装路径是…...
《AI 之影》
《AI 之影》 城市的喧嚣如同一幅永不停息的画卷,在钢筋水泥的丛林中,人们匆忙地穿梭,追逐着各自的梦想与欲望。而在这看似平凡的都市之中,一场悄然的变革正在酝酿。 他叫佑介,一个孤独的城市漫步者。每天,他…...
QT5.14*解决QSslSocket::connectToHostEncrypted: TLS initialization faile
qDebug()<<"QSslSocket"<<QSslSocket::sslLibraryBuildVersionString();通过上述代码在QT控制台查看对应需要的SSL版本,QT5.14.*输出的内容为: OpenSSL 1.1.1d 10 Sep 2019从官方下载openssl安装包即可,在官网找了很…...
高效分支管理规范
一、目的 通过标准化的流程和最佳实践,确保代码组织清晰、版本控制高效、变更管理有序,从而提高软件开发的质量、效率和可维护性,支持团队协作和持续集成/持续部署流程,最终实现项目的长期成功和发展 二、分支命名规范 简洁明了…...
跟我学C++中级篇——RAII
一、什么是RAII Resource Acquisition Is Initialization,资源获取即初始化。C/C的开发者都知道,在这类语言的开发中,内存需要手动来控制。也就是说,释放和回收内存得开发者亲历亲为。从某种角度看,能够把控内存的细节…...
C语言第九周课——经典算法
目录 一、冒泡法排序 1.1原理 1.2代码实现(以升序排序为例) 1.3逻辑 1.4分析 二、二分法查找 2.1原理 2.2代码实现 2.3逻辑 2.4算法效率分析 三、素数判断 3.1原理 3.2代码实现 3.3逻辑 3.4分析 一、冒泡法排序 1.1原理 冒泡排序&…...
【Pikachu】XML外部实体注入实战
若天下不定,吾往;若世道不平,不回! 1.XXE漏洞实战 首先写入一个合法的xml文档 <?xml version "1.0"?> <!DOCTYPE gfzq [<!ENTITY gfzq "gfzq"> ]> <name>&gfzq;</name&…...
vue2项目中在线预览csv文件
简介 希望在项目中,在线预览.csv文件,本以为插件很多,结果都只是支持excel(.xls、.xlsx)一到.csv就歇菜。。。 关于文件预览 vue-office:文档、 查看在线演示demo,支持docx、.xlsx、pdf、ppt…...
基于VUE实现语音通话:边录边转发送语言消息、 播放pcm 音频
文章目录 引言I 音频协议音频格式:音频协议:II 实现协议创建ws对象初始化边录边转发送语言消息 setupPCM按下通话按钮时开始讲话,松开后停止讲话播放pcm 音频III 第三库recorderplayer调试引言 需求:电台通讯网(电台远程遥控软件-超短波)该系统通过网络、超短波终端等无线…...
PMP--一、二、三模、冲刺--分类--变更--技巧--特点
文章目录 一模二模三模冲刺14.敏捷--不确定性、风险和生命周期选择14.敏捷--特点--敏捷范围灵活,敏捷拥抱变更14.敏捷--阶段关口--在不同的组织、行业或工作类型中,阶段关口可能被称为阶段审查、阶段门、关键决策点和阶段入口或阶段出口。组织可以通过这…...
CSS Grid 布局实战:从入门到精通
文章目录 前言一、CSS Grid 布局概述1.1 什么是 CSS Grid 布局?1.2 主要特点 二、基本概念2.1 网格容器2.2 网格线2.3 网格轨道2.4 网格区域 三、常用属性3.1 定义网格结构3.2 控制网格项的位置3.3 控制网格间距3.4 自动填充和重复 四、实践案例4.1 项目结构4.2 HTM…...
git创建远程仓库,以gitee码云为例GitHub同理
git远程Remote服务端仓库构建的视频教程在这 Git建立服务端Remote远程仓库,gitee码云例,Github_哔哩哔哩_bilibili 1、登gitee码云/Github 登录 - Gitee.com https://github.com/ (没账号的注册一下就行) 点击如下图位置的创…...
Java爬虫(HttpURLConnection)详解
文章目录 Java爬虫(HttpURLConnection)详解一、引言二、准备工作1、环境配置2、理解HttpURLConnection 三、发送GET请求1、创建URL对象2、打开连接3、设置请求方法4、连接并读取响应5、处理返回的数据 四、发送POST请求1、设置输出2、发送请求体3、读取响…...
Windows系统优化新范式:Win11Debloat技术原理与实践指南
Windows系统优化新范式:Win11Debloat技术原理与实践指南 【免费下载链接】Win11Debloat 一个简单的PowerShell脚本,用于从Windows中移除预装的无用软件,禁用遥测,从Windows搜索中移除Bing,以及执行各种其他更改以简化和…...
Miniconda环境迁移实战:如何将CentOS装好的Python环境打包到其他服务器?
Miniconda环境迁移实战:跨服务器Python环境无缝转移指南 当你在CentOS服务器上精心配置了一个完美的Python数据分析环境,却需要在另一台服务器上复现时,难道要重新经历一遍繁琐的安装过程?本文将揭示两种高效可靠的Miniconda环境迁…...
PyTorch实战(38)——深度学习模型可解释性
PyTorch实战(38)——深度学习模型可解释性0. 前言1. PyTorch 模型可解释性2. 训练手写数字分类器3. 可视化模型卷积核4. 可视化特征图小结系列链接0. 前言 在本专栏中,我们已经构建了多种深度学习模型来完成不同任务,包括手写数字…...
Agent-S智能自动化框架:企业级系统集成的技术解决方案
Agent-S智能自动化框架:企业级系统集成的技术解决方案 【免费下载链接】Agent-S Agent S: an open agentic framework that uses computers like a human 项目地址: https://gitcode.com/GitHub_Trending/ag/Agent-S 在当今快速发展的数字化转型浪潮中&#…...
【SOC】Fastboot /DFU 烧录镜像
uboot下 使用fastboot 进行 UFS/EMMC/nand 设备烧录的大致流程: board 进入 uboot(支持 fastboot); 同时host机器安装上 fastboot 客户端 ; 2者(board与host)之间通过usb线连接,通过fastboot 协议进行交互…...
保姆级教程:在OrangePi 5 Plus上从SSD启动Ubuntu 22.04,并配置ROS2 Humble环境
OrangePi 5 Plus开发板全栈配置指南:从SSD启动到ROS2 Humble环境搭建 拿到一块OrangePi 5 Plus开发板时,如何快速搭建一个稳定高效的开发环境?本文将手把手带你完成从系统烧录到ROS2环境配置的全过程,特别针对ARM64架构的优化方案…...
LangGPT结构化提示词框架:重新定义AI交互的核心方法
LangGPT结构化提示词框架:重新定义AI交互的核心方法 【免费下载链接】LangGPT LangGPT: Empowering everyone to become a prompt expert!🚀 Structured Prompt,Language of GPT, 结构化提示词,结构化Prompt 项目地址: https://…...
OpCore-Simplify:如何用四步自动化流程解决黑苹果配置的三大核心挑战
OpCore-Simplify:如何用四步自动化流程解决黑苹果配置的三大核心挑战 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 对于黑苹果爱好者来说…...
用MATLAB从零实现六足机器人步态:交替三角与波动步态代码详解
用MATLAB从零实现六足机器人步态:交替三角与波动步态代码详解 六足机器人因其卓越的稳定性和地形适应能力,在野外勘探、灾难救援等领域展现出巨大潜力。而步态规划作为机器人运动控制的核心,直接决定了机器人的移动效率和稳定性。本文将带您从…...
全球蛋白质组学数据共享核心平台升级
摘要 ProteomeXchange蛋白质组学资源联盟(http://www.proteomexchange.org)的建立旨在标准化基于质谱(MS)的蛋白质组学领域开放数据实践。本文介绍了ProteomeXchange在过去3年的主要进展。该联盟的6个成员数据库分布于࿱…...
