欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > Uni-App 双栏联动滚动组件开发详解 (电梯导航)

Uni-App 双栏联动滚动组件开发详解 (电梯导航)

2025/3/22 7:44:38 来源:https://blog.csdn.net/weixin_66591252/article/details/146391619  浏览:    关键词: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>

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词