uniapp上实现左右关联滚动
先看效果:

代码:
<template><view class="container"><!-- 左侧fixed导航区域 --><view class="left"><viewv-for="item in leftList":key="item.id"class="left_item":class="item.id == selectedId ? 'selected' : ''"@click="leftItemClick(item.id)">{{ item.title }}</view></view><!-- 右侧内容区域 --><view class="right"><view v-for="item in rightList" :key="item.id" class="right_item">{{ item.content }}</view></view></view>
</template><script>
export default {data() {return {leftList: [],rightList: [],selectedId: 1, //左边当前选中iditemTopArr: [], //右侧所有item的top数组};},onLoad() {this.initData();this.getItemTopArr();},//页面滚动监听onPageScroll(e) {let scrollTop = e.scrollTop;console.log("scrollTop = " + scrollTop);for (let i = 0; i < this.itemTopArr.length; i++) {if (scrollTop >= this.itemTopArr[i]) {this.selectedId = this.rightList[i].parentId;console.log("selectedId = " + this.selectedId);}}},methods: {//左侧item点击leftItemClick(id) {this.selectedId = id;let index = 0;for (let i = 0; i < this.rightList.length; i++) {if (this.rightList[i].parentId == id) {index = i;break;}}//将页面滚动到目标位置uni.pageScrollTo({scrollTop: this.itemTopArr[index],duration: 300, //滚动动画时长});},//获取右侧所有item的top数组getItemTopArr() {this.$nextTick(() => {const query = uni.createSelectorQuery().in(this);const nodesRef = query.selectAll(".right > .right_item");nodesRef.fields({size: true,rect: true,scrollOffset: true,},(res) => {res.forEach((item) => {this.itemTopArr.push(item.top);});console.log(this.itemTopArr);}).exec();});},//初始化数据源initData() {for (let index = 1; index < 10; index++) {for (let i = 1; i < 4; i++) {this.rightList.push({id: index + "-" + i,parentId: index,content: "content-" + index,});}this.leftList.push({id: index,title: "title-" + index,});}},},
};
</script><style lang="scss" scoped>
.container {position: relative;min-height: 100vh;background: #fff;.left {position: fixed;width: 120px;height: 100%;min-height: 100vh;overflow: auto;float: left;background: #f2f2f2;.left_item {width: 100%;height: 60px;text-align: center;line-height: 60px;}.selected {background: #fff;font-weight: bold;color: #07c160;}}.right {margin-left: 120px;width: calc(100vw - 120px);overflow: auto;.right_item {width: 100%;height: 200px;text-align: center;line-height: 200px;font-size: 24px;border-bottom: 1px solid #ccc;box-sizing: border-box; //padding、border不影响元素的宽高}}
}
</style>

官方onPageScroll方法的使用注意事项(见上图)里说不要在此方法里写复杂的交互,故将onPageScroll里的for循环改写到滚动结束执行:
<template><view class="container"><!-- 左侧fixed导航区域 --><view class="left"><viewv-for="item in leftList":key="item.id"class="left_item":class="item.id == selectedId ? 'selected' : ''"@click="leftItemClick(item.id)">{{ item.title }}</view></view><!-- 右侧内容区域 --><view class="right"><view v-for="item in rightList" :key="item.id" class="right_item">{{ item.content }}</view></view></view>
</template><script>
export default {data() {return {leftList: [],rightList: [],selectedId: 1, //左边当前选中iditemTopArr: [], //右侧所有item的top数组timeoutID: null,};},onLoad() {this.initData();this.getItemTopArr();},//页面滚动监听onPageScroll(e) {let scrollTop = e.scrollTop;console.log("scrollTop = " + scrollTop);clearTimeout(this.timeoutID);this.timeoutID = setTimeout(() => {console.log("结束滚动");for (let i = 0; i < this.itemTopArr.length; i++) {if (scrollTop >= this.itemTopArr[i]) {this.selectedId = this.rightList[i].parentId;console.log("selectedId = " + this.selectedId);}}}, 100);},methods: {//左侧item点击leftItemClick(id) {this.selectedId = id;let index = 0;for (let i = 0; i < this.rightList.length; i++) {if (this.rightList[i].parentId == id) {index = i;break;}}//将页面滚动到目标位置uni.pageScrollTo({scrollTop: this.itemTopArr[index],duration: 300, //滚动动画时长success: (res) => {console.log(res);console.log("scroll success");},fail: (err) => {console.log(err);console.log("scroll fail");},});},//获取右侧所有item的top数组getItemTopArr() {this.$nextTick(() => {const query = uni.createSelectorQuery().in(this);const nodesRef = query.selectAll(".right > .right_item");nodesRef.fields({size: true,rect: true,scrollOffset: true,},(res) => {res.forEach((item) => {this.itemTopArr.push(item.top);});console.log(this.itemTopArr);}).exec();});},//初始化数据源initData() {for (let index = 1; index < 10; index++) {for (let i = 1; i < 4; i++) {this.rightList.push({id: index + "-" + i,parentId: index,content: "content-" + index,});}this.leftList.push({id: index,title: "title-" + index,});}},},
};
</script><style lang="scss" scoped>
.container {position: relative;min-height: 100vh;background: #fff;.left {position: fixed;width: 120px;height: 100%;min-height: 100vh;overflow: auto;float: left;background: #f2f2f2;.left_item {width: 100%;height: 60px;text-align: center;line-height: 60px;}.selected {background: #fff;font-weight: bold;color: #07c160;}}.right {margin-left: 120px;width: calc(100vw - 120px);overflow: auto;.right_item {width: 100%;height: 200px;text-align: center;line-height: 200px;font-size: 24px;border-bottom: 1px solid #ccc;box-sizing: border-box; //padding、border不影响元素的宽高}}
}
</style>相关文章:
uniapp上实现左右关联滚动
先看效果: 代码: <template><view class"container"><!-- 左侧fixed导航区域 --><view class"left"><viewv-for"item in leftList":key"item.id"class"left_item":class…...
Docker Remote API未授权访问
目录Docker简述Docker 2375端口安全风险Docker命令连接利用声明:本文仅供学习参考,其中涉及的一切资源均来源于网络,请勿用于任何非法行为,否则您将自行承担相应后果,本人不承担任何法律及连带责任。Docker简述 Docke…...
【蓝桥杯】第十四届蓝桥杯模拟赛(第三期)C++ (弱go的记录,有问题的话求指点)
博主是菜鸡啦,代码仅供参考,只确定能过样例,嘻嘻~第一题,填空题问题描述请找到一个大于 2022 的最小数,这个数转换成十六进制之后,所有的数位(不含前导 0)都为字母(A 到 …...
算法24:LeetCode_并查集相关算法
目录 题目一:力扣547题,求省份数量 题目二:岛屿数量 题目三:岛屿数量拓展 什么是并查集,举个简单的例子。学生考试通常会以60分为及格分数,我们将60分及以上的人归类为及格学生,而60分以下归…...
TypeScript核心知识点
TypeScript 核心 类型注解 知道:TypeScript 类型注解 示例代码: // 约定变量 age 的类型为 number 类型 let age: number 18 age 19: number 就是类型注解,它为变量提供类型约束。约定了什么类型,就只能给该变量赋值什么类型的…...
基于“遥感+”融合技术在碳储量、碳收支、碳循环等多领域监测与模拟实践
以全球变暖为主要特征的气候变化已成为全球性环境问题,对全球可持续发展带来严峻挑战。2015年多国在《巴黎协定》上明确提出缔约方应尽快实现碳达峰和碳中和目标。2019年第49届 IPCC全会明确增加了基于卫星遥感的排放清单校验方法。随着碳中和目标以及全球碳盘点的现…...
外卖点餐系统小程序 PHP+UniAPP
一、介绍 本项目是给某大学餐厅开发的外面点餐系统,该项目针对校内的学生,配送由学校的学生负责配送。因此,该项目不同于互联网的外卖点餐系统。 该系统支持属于 Saas 系统,由平台端、商家端、用户端、以及配送端组成。 其中&a…...
vuex3的介绍与state、actions和mutations的使用
一、定义官网:Vuex 是什么? | Vuex (vuejs.org)Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。二、安装cdn<script src"/path/…...
windows 自带端口转发
使用Portproxy模式下的Netsh命令即能实现Windows系统中的端口转发,转发命令如下: netsh interface portproxy add v4tov4 listenaddress[localaddress] listenport[localport] connectaddress[destaddress]listenaddress – 等待连接的本地ip地址 listenport – 本…...
【算法】算法基础入门详解:轻松理解和运用基础算法
😀大家好,我是白晨,一个不是很能熬夜😫,但是也想日更的人✈。如果喜欢这篇文章,点个赞👍,关注一下👀白晨吧!你的支持就是我最大的动力!Ǵ…...
2.9.1 Packet Tracer - Basic Switch and End Device Configuration(作业)
Packet Tracer - 交换机和终端设备的基本 配置地址分配表目标使用命令行界面 (CLI),在两台思科互联网络 操作系统 (IOS) 交换机上配置主机名和 IP 地址。使用思科 IOS 命令指定或限制对设备 配置的访问。使用 IOS 命令来保存当前的运行配置。配置两台主机设备的 IP …...
AtCoder Beginner Contest 216(F)
F - Max Sum Counting 链接: F - Max Sum Counting 题意 两个 大小为 nnn 的序列 aiaiai 和 bibibi,任意选取一些下标 iii,求 max(ai)>∑bi\max(ai) > \sum{bi}max(ai)>∑bi的方案数。 解析 首先考虑状态 一是和,…...
每天学一点之Stream流相关操作
StreamAPI 一、Stream特点 Stream是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。“集合讲的是数据,负责存储数据,Stream流讲的是计算,负责处理数据!” 注意: ①Str…...
MatCap模拟光照效果实现
大家好,我是阿赵 之前介绍过各种光照模型的实现方法。那些光照模型的实现虽然有算法上的不同,但基本上都是灯光方向和法线方向的计算得出的明暗结果。 下面介绍一种叫做MatCap的模拟光照效果,这种方式计算非常简单,脱离灯光的计算…...
二十一、PG管理
一、 PG异常状态说明 1、 PG状态介绍 可以通过ceph pg stat命令查看PG当前状态,健康状态为“active clean” [rootrbd01 ~]# ceph pg stat 192 pgs: 192 activeclean; 1.3 KiB data, 64 MiB used, 114 GiB / 120 GiB avail; 85 B/s rd, 0 op/s2、pg常见状态 状…...
SAPUI5开发01_01-Installing Eclipse
1.0 简要要求概述: 本节您将安装SAPUI 5,以及如何在Eclipse Juno中集成SAPUI 5工具。 1.1 安装JDK JDK 是一种用于构建在 Java 平台上发布的应用程序、Applet 和组件的开发环境,即编写 Java 程序必须使用 JDK,它提供了编译和运行 Java 程序的环境。 在安装 JDK 之前,首…...
Qt之高仿QQ系统设置界面
QQ或360安全卫士的设置界面都是非常有特点的,所有的配置项都在一个垂直的ScrollArea中,但是又能通过左侧的导航栏点击定位。这样做的好处是既方便查看指定配置项,又方便查看所有配置项。 一.效果 下面左边是当前最新版QQ的系统设置界面,右边是我的高仿版本,几乎一毛一样…...
JVM概览:内存空间与数据存储
核心的五个部分虚拟机栈:局部变量中基础类型数据、对象的引用存储的位置,线程独立的。堆:大量运行时对象都在这个区域存储,线程共享的。方法区:存储运行时代码、类变量、常量池、构造器等信息,线程共享。程…...
固态存储设备固件升级方案
1. 前言 随着数字化时代的发展,数字数据的量越来越大,相应的数据存储的需求也越来越大,存储设备产业也是蓬勃发展。存储设备产业中,发展最为迅猛的则是固态存储(Solid State Storage,SSS)。数字化时代,海量…...
Python交通标志识别基于卷积神经网络的保姆级教程(Tensorflow)
项目介绍 TensorFlow2.X 搭建卷积神经网络(CNN),实现交通标志识别。搭建的卷积神经网络是类似VGG的结构(卷积层与池化层反复堆叠,然后经过全连接层,最后用softmax映射为每个类别的概率,概率最大的即为识别…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
Python 实现 Web 静态服务器(HTTP 协议)
目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1)下载安装包2)配置环境变量3)安装镜像4)node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1)使用 http-server2)详解 …...
