Uni-App 双栏联动滚动组件开发详解 (电梯导航)
本文基于提供的代码实现一个左右联动的滚动组件,以下是详细的代码解析与实现原理说明:
<!--双栏联动滚动组件 - 技术解析功能特性:1. 左侧导航栏与右侧内容区双向联动2. 自适应容器高度3. 平滑滚动定位4. 动态内容位置计算
-->
<template><view class="container"><!-- 外层容器 --><view class="nav-container" id="navContainer"><!-- 左侧导航 ScrollView --><scroll-view:scroll-y="true":style="{ height: containerHeight + 'px' }"class="nav-sidebar":scroll-into-view="leftScrollId"scroll-with-animation><!-- 导航项循环渲染 --><viewv-for="(item, index) in leftData":key="index":id="'navItem-' + index":class="['nav-item', { active: currentIndex === index }]"@tap="handleNavClick(index)">{{ item }}</view></scroll-view><!-- 右侧内容 ScrollView --><scroll-view:scroll-y="true":style="{ height: containerHeight + 'px' }"class="content-main":scroll-into-view="rightScrollId"@scroll="handleContentScroll"scroll-with-animation><!-- 内容区块循环渲染 --><viewv-for="(section, sIndex) in rightData":key="sIndex":id="'content-' + sIndex"class="content-section"><view class="section-title">{{ section.title }}</view><viewv-for="(para, pIndex) in section.content":key="pIndex"class="content-para">{{ para }}</view></view><view :style="{ height: fillHeight + 'px' }"></view></scroll-view></view></view>
</template><script>export default {// 组件参数定义props: {leftData: {// 左侧导航数据type: Array,default: () => ['章节1', '章节2', '章节3', '章节4', '章节5', '章节6'],},rightData: {// 右侧内容数据type: Array,default: () => [{title: '章节1',content: ['内容1'],},{title: '章节2',content: ['内容1'],},{title: '章节3',content: ['内容1'],},{title: '章节4',content: ['内容1'],},{title: '章节5',content: ['内容1'],},],},},// 组件状态管理data() {return {containerTop: 0, //容器距离顶部距离containerHeight: 500, // 容器动态高度currentIndex: 0, // 当前激活索引sectionPositions: [], // 章节位置缓存数组positionsReady: false, // 位置计算完成标志fillHeight: 50, // 填充盒子的高度,内容滚动最后一项增加高度方便滚动}},// 计算属性computed: {// 左侧导航自动定位ID(保持选中项在可视区)leftScrollId() {return `navItem-${Math.max(this.currentIndex - 2, 0)}` // 提前2项滚动},// 右侧内容自动定位IDrightScrollId() {return `content-${this.currentIndex}`},},// 生命周期钩子mounted() {this.initContainer().then(() => this.calcSectionPositions()).catch(console.error)},// 组件方法methods: {/*** 初始化容器尺寸* 使用 Promise 保证高度计算完成*/initContainer() {return new Promise((resolve) => {uni.createSelectorQuery().in(this).select('#navContainer').boundingClientRect((res) => {this.containerTop = res.top //距离父元素顶部高度this.containerHeight = res.heightresolve()}).exec()})},/*** 计算内容区块位置* 使用 uni API 获取元素位置信息*/calcSectionPositions() {uni.createSelectorQuery().in(this).selectAll('.content-section').boundingClientRect((res) => {// 缓存各章节顶部位置this.sectionPositions = res.map((item) => item.top - this.containerTop)this.positionsReady = truelet lastHeight = res[res.length - 1].heightconsole.log(this.containerHeight, 8454545)//如果滚动显示的区域大于右侧单个元素的高度就要加入填充高度让元素滚动的时候 左侧的标签可以正常切换if (lastHeight- 20 < this.containerHeight ) {this.fillHeight = this.containerHeight - last + 20}}).exec()},/*** 导航点击处理* @param {number} index - 点击的导航索引*/handleNavClick(index) {this.currentIndex = index // 更新当前索引},/*** 内容滚动处理* @param {Object} e - 滚动事件对象*/handleContentScroll(e) {if (!this.positionsReady) returnconst scrollTop = e.detail.scrollTopconst positions = this.sectionPositions// 二分查找算法优化(当前使用顺序查找)let current = this.currentIndexwhile (current < positions.length && positions[current] < scrollTop + 50) {current++}this.currentIndex = Math.max(current - 1, 0)},},}
</script><!-- 样式设计说明 -->
<style>/* 容器布局 */.container {height: 20vh; /* 全屏高度 */background: #ffffff;}.nav-container {display: flex; /* 弹性布局 */height: 100%;}/* 左侧导航样式 */.nav-sidebar {width: 200rpx; /* 固定宽度 */background: #f5f7fa; /* 浅色背景 */border-right: 1px solid #e4e7ed;}.nav-item {padding: 24rpx;transition: all 0.3s; /* 平滑过渡效果 */}.nav-item.active {color: #409eff; /* 主题色 */background: #ecf5ff; /* 激活背景 */}/* 右侧内容样式 */.content-main {flex: 1; /* 剩余空间填充 */padding: 32rpx;}.section-title {font-size: 36rpx; /* 标题字号 */font-weight: 600;}.content-para {background: #fafafa; /* 段落背景 */border-radius: 8rpx;}
</style>
技术实现要点
1. 双向滚动联动机制
- 导航 → 内容:通过
scroll-into-view绑定计算属性,点击时自动定位 - 内容 → 导航:监听滚动事件,计算当前可见章节并更新激活状态
2. 性能优化设计
- 位置信息缓存:预先计算章节位置,避免频繁查询DOM
- 节流处理:滚动事件默认自带节流,保证性能
- 异步计算:使用 Promise 链保证初始化顺序
3. 自适应布局
- 动态高度计算:通过 uni API 获取容器实际高度
- Flex 布局:实现左右栏自适应排列
4. 扩展性考虑
- 组件化设计:通过 props 接收数据,方便复用
- 样式可配置:通过 class 控制样式,易于主题定制
使用示例
<template><dual-scroll :left-data="categories" :right-data="contents"/>
</template><script>
// 示例数据结构
const categories = ['水果', '蔬菜', '肉类']
const contents = [{title: '水果',content: ['苹果', '香蕉', '橙子']},{title: '蔬菜',content: ['白菜', '萝卜', '番茄']}
]
</script>
相关文章:
Uni-App 双栏联动滚动组件开发详解 (电梯导航)
本文基于提供的代码实现一个左右联动的滚动组件,以下是详细的代码解析与实现原理说明: <!--双栏联动滚动组件 - 技术解析功能特性:1. 左侧导航栏与右侧内容区双向联动2. 自适应容器高度3. 平滑滚动定位4. 动态内容位置计算 --> <te…...
当下主流 AI 模型对比:ChatGPT、DeepSeek、Grok 及其他前沿技术
📝个人主页🌹:一ge科研小菜鸡-CSDN博客 🌹🌹期待您的关注 🌹🌹 1. 引言 人工智能(AI)领域近年来取得了巨大的突破,特别是在大语言模型(LLM&#…...
【自用】NLP算法面经(5)
一、L1、L2正则化 正则化是机器学习中用于防止过拟合并提高模型泛化能力的技术。当模型过拟合时,它已经很好地学习了训练数据,甚至是训练数据中的噪声,所以可能无法在新的、未见过的数据上表现良好。 比如: 其中,x1和…...
体育直播视频源格式解析:M3U8 vs FLV
在体育直播领域,视频源的格式选择直接影响着直播的流畅度、画质以及兼容性。目前,M3U8 和 FLV 是两种最为常见的视频流格式,它们各有优劣,适用于不同的场景。本文将从技术原理、优缺点以及应用场景等方面对 M3U8 和 FLV 进行详细解…...
Ubuntu20.04安装并配置Pycharm2020.2.5
一. 下载pycharm 社区版 1. 下载地址: PyCharm: the Python IDE for data science and web developmentThe Python IDE for data science and web development with intelligent code completion, on-the-fly error checking, quick-fixes, and much more.https:/…...
Filter Solutions学习-02 【高级设计】界面介绍
这是高级界面的各种控件的功能。 其中说一下filter type。这不是根据自己想当然决定的,而是根据实际的需要,比如带外衰减的程度,带内波动(平坦)如何,还有群时延等等决定的。比如不要求矩形系数选什么。。 …...
用Python实现交互式数据可视化:从基础图表到动态仪表板
用Python实现交互式数据可视化:从基础图表到动态仪表板 一、项目背景 本文将通过一个完整的Python项目,展示如何使用Plotly和ipywidgets构建从基础统计到动态交互的全栈数据可视化方案。 二、核心功能模块 1. 数据生成与预处理 np.random.seed(100)…...
Java面试黄金宝典5
1. ConcurrentHashMap 和 HashTable 有哪些区别 原理 HashTable:它继承自 Dictionary 类,是 Java 早期提供的线程安全哈希表。其线程安全的实现方式是对每个方法都使用 synchronized 关键字进行同步。例如,在调用 put、get 等方法时ÿ…...
【深度学习与大模型基础】第6章-对角矩阵,对称矩阵,正交矩阵
一、对角矩阵 对角矩阵(Diagonal Matrix)是一种特殊的方阵,其非对角线上的元素均为零,只有对角线上的元素可能非零。具体来说,对于一个 nn的矩阵 A[],如果满足 则 AA 称为对角矩阵。对角矩阵通常表示为&am…...
初识R语言饼状图
目录 基础饼图 标签个性化 边界修改 密度条纹 边框颜色 基础饼图 rm(list ls())# Create Data Prop <- c(3,7,9,1,2) # Make the default Pie Plot P1 <- pie(Prop) dev.off() 标签个性化 P2 <-pie(Prop , labels c("Gr-A","Gr-B","…...
计算机技术系列博客——目录页(持续更新)
1.1 博客目录专栏 1.1.1 博客文章导航 计算机技术系列博客——目录页 1.1.2 网页资源整理 2.1 计算机科学理论 2.2 软件工程技术 2.2.1.1 编程语言 Java Java语言基础 (1) Java基础知识总结01——Java基础篇 (2) Java基础知识总结02——集合框架篇 (3) Java基础知识总结03—…...
HTTP和RPC的区别
RPC和 HTTP是两种常见的通信方式,它们在设计目标、使用场景和技术实现上有显著区别。以下是它们的详细对比: 1. 定义与核心思想 特性RPCHTTPRemote Procedure Call远程过程调用HyperText Transfer Protocol超文本传输协议定义一种协议或框架࿰…...
Spring MVC 拦截器使用
javaweb过滤器和springmvc拦截器: 拦截器的概念 拦截器使用 1/创建拦截器类,类中实现 handler执行前,执行后与渲染视图后的具体实现方法 public class GlobalExceptionHandler implements HandlerInterceptor {// if( ! preHandler()){re…...
汽车机械钥匙升级一键启动的优点
汽车机械钥匙升级一键启动的优点主要包括: 便捷性:一键启动功能的引入极大地提升了用车便捷性。车主无需翻找钥匙,只需在车辆感应范围内轻触启动键,即可轻松发动汽车。 安全性:移动管家专车专用一键启动系统配备了防…...
中小企业如何低成本构建高效专属网络?
对于许多中小企业管理者而言,构建一套安全、灵活且可扩展的专网系统是数字化转型的“必修课”。本文将从实际业务场景出发,拆解企业组网的核心步骤,并提供可落地的实施方案建议,帮助您快速匹配适合自身需求的网络服务商。 一、组网…...
实用工具-Stirling-PDF
windows桌面版参考这个文档 Getting Started | Stirling-PDF 安装包推荐使用迅雷下载,先转存到迅雷网盘在使用迅雷下载速度嘎嘎快。 github:https://github.com/Stirling-Tools/Stirling-PDF Stirling-PDF 是一个强大的、基于 Web 的开源 PDF 处理工具,…...
【C++】 —— 笔试刷题day_6
刷题day_6,继续加油哇! 今天这三道题全是高精度算法 一、大数加法 题目链接:大数加法 题目解析与解题思路 OK,这道题题目描述很简单,就是给我们两个字符串形式的数字,让我们计算这两个数字的和 看题目我…...
pytorch 网络结构可视化Netron安装使用方法(已解决)
首先 要把保存的训练模型 转为onnx格式的文件,然后打开下面的链接,选择刚刚转的onnx文件。 下载 Netron: 您可以访问 Netron 的官方网站 在线使用,或者下载桌面版本。 mnist_cnn_model.onnx 确定后, 2、TensorRT学习…...
QEMU 中 x86_cpu_realizefn 到 ept_emulation_fault 的调用流程解析(macos)
QEMU 中 x86_cpu_realizefn 到 ept_emulation_fault 的调用流程解析 在 QEMU 的 x86 虚拟化实现中,CPU 的初始化与执行流程涉及多个关键函数,从 CPU 设备的最终初始化(x86_cpu_realizefn)到虚拟机监控程序(HVF&#x…...
第六:go 操作 redis-go
Redis 在项目开发中redis的使用也比较频繁,本文介绍了Go语言中go-redis库的基本使用。 Redis介绍 Redis是一个开源的内存数据库,Redis提供了多种不同类型的数据结构,很多业务场景下的问题都可以很自然地映射到这些数据结构上。除此之外&am…...
【蓝桥杯】每天一题,理解逻辑(4/90)【Leetcode 二进制求和】
题目描述 我们解析一下题目 我们可以理解到两个主要信息 给的是二进制的字符串返回他们的和 我们知道,十进制的加减法需要进位,例如:9716是因为91之后进了一位,二进制也是如此,只不过十进制是逢10进1,二…...
CentOS 7 更换 YUM 源为国内
**CentOS 7 更换 YUM 源为国内源 ** 背景说明 更换 YUM 源可加速软件下载,解决官方源访问慢的问题。国内推荐镜像源:阿里云、清华、网易、中科大。 一、备份原有 YUM 源 # 备份系统默认源(避免操作失误可恢复) sudo cp /etc/yum…...
快速入手-基于Django的mysql配置(三)
Django开发操作数据库更简单,内部提供了ORM框架。比如mysql,旧版本用pymysql对比较多,新的版本采用mysqlclient。 1、安装mysql模块 pip install mysqlclient 2、Django的ORM主要做了两件事 (1)CRUD数据库中的表&am…...
docker部署dify
1.安装docker 参考链接 https://ascendking.blog.csdn.net/article/details/136407383 设置docker源 vim /etc/docker/daemon.json {"registry-mirrors": ["https://docker.registry.cyou", "https://docker-cf.registry.cyou", "http…...
网络安全红蓝对抗实战演练,沉浸式对抗训练场上线!
在网络安全的世界里,没有永恒的盾牌,只有不断磨砺的利剑。近年来,某金融机构因系统漏洞导致千万级用户数据泄露,某制造企业因生产线遭遇勒索攻击被迫停产数日——这些真实案例揭示了一个残酷现实:传统的理论教学已无法…...
舞狮表演(dp)
#include <bits/stdc.h> using namespace std; const int N1e35; int main() {int t;cin>>t;while(t--){int n;cin>>n;int a[N][N];for(int i1;i<n;i){for(int j1;j<n;j){int x;cin>>x;if(x&1) a[i][j]1; // 如果金额是奇数,a[i]…...
【Qt】Qt + Modbus 服务端学习笔记
《Qt Modbus 服务端学习笔记》 1.因为项目的需要,要写一个modbus通信,csdn上感觉有些回答,代码是人工智能生成的,有些细节不对。我这个经过实测,是可以直接用的。 首先要包含Qt 的相关模块 Qt Modbus 模块主要包含以…...
squirrel语言全面介绍
Squirrel 是一种较新的程序设计语言,由意大利人 Alberto Demichelis 开发,其设计目标是成为一个强大的脚本工具,适用于游戏等对大小、内存带宽和实时性有要求的应用程序。以下是对 Squirrel 语言的全面介绍: 语言特性 动态类型&a…...
SpringBoot配置文件加载优先级
目录 示例 配置文件&编写配置类 在Spring Boot项目中,配置属性的优先级是一个重要的概念,它决定了当存在多个配置源时,哪个配置源的属性将被应用。以下是SpringBoot中配置属性的优先级,从最高到最低: 命令行参数…...
【详细解决】pycharm 终端出现报错:“Failed : 无法将“Failed”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。
昨天在终端一顿操作后突然打开pycharm时就开始报错: 无法将“Failed”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。 所在位置 行:1 字符: 1 Failed to act…...
