uniapp使用scroll-into-view实现锚点定位和滚动监听功能【楼层效果 / 侧边导航联动效果】

大佬网址:

https://blog.csdn.net/weixin_47136265/article/details/132303570

效果

请添加图片描述

代码

<template><view class="main"><scroll-view scroll-y="true" class="left-content"><view class="left-item" :class="{ 'activeItem': tabIndex == index }" v-for="(item,index) in leftData":key="item.id" @click="clickLeftItem(index)">{{item.title}}</view></scroll-view><scroll-view scroll-y="true" class="right-content" :scroll-into-view="scrollId" scroll-with-animation@scroll="scrollEvt"><view class="right-item" v-for="(item,index) in rightData" :key="item.id" :id="'item'+index"><view class="title">{{item.title}}</view><view class="content"><view class="content-item" v-for="itm in item.children" :key="itm.id">{{itm.text}}</view></view></view></scroll-view></view>
</template>
<script>export default {data() {return {tabIndex: 0,scrollId: '',distanceList: [],timer: null,isLeftClick: false,leftData: [{title: '第一个',id: 10001},{title: '第二个',id: 10002},{title: '第三个',id: 10003},{title: '第四个',id: 10004},{title: '第五个',id: 10005},{title: '第六个',id: 10006}],rightData: [{id: '20001',title: '第一部分标题',children: [{id: '30001',text: '第一个子项'},{id: '30002',text: '第二个子项'},{id: '30003',text: '第三个子项'},{id: '30004',text: '第四个子项'}]},{id: '20002',title: '第二部分标题',children: [{id: '30005',text: '第一个子项'},{id: '30006',text: '第二个子项'},{id: '30007',text: '第三个子项'}]},{id: '20003',title: '第三部分标题',children: [{id: '30008',text: '第一个子项'},{id: '30009',text: '第二个子项'},{id: '30010',text: '第三个子项'},{id: '30011',text: '第四个子项'}]},{id: '20004',title: '第四部分标题',children: [{id: '30012',text: '第一个子项'},{id: '30013',text: '第二个子项'}]},{id: '20005',title: '第五部分标题',children: [{id: '300014',text: '第一个子项'},{id: '300015',text: '第二个子项'}]},{id: '20006',title: '第六部分标题',children: [{id: '300016',text: '第一个子项'},{id: '300017',text: '第二个子项'},{id: '300018',text: '第三个子项'},{id: '300019',text: '第四个子项'}]}]}},mounted() {setTimeout(() => {this.getDistanceToTop();}, 500)},methods: {clickLeftItem(index) {this.isLeftClick = truethis.tabIndex = indexthis.scrollId = 'item' + index},getDistanceToTop() { //获取右侧各部分距离顶部的距离let that = thislet selectorQuery = uni.createSelectorQuery().in(this);selectorQuery.selectAll('.right-item').boundingClientRect(function(rects) {rects.forEach(function(rect) {that.distanceList.push(rect.top)})console.log('that.distanceList', that.distanceList);}).exec()},// 元素滚动到顶部时,对应的左侧导航栏变为选中状态scrollEvt(e) {// 点击左侧导航栏引起的滚动不做判断if (this.isLeftClick) {this.isLeftClick = falsereturn}// 防抖if (this.timer) {clearTimeout(this.timer)}this.timer = setTimeout(() => {let scrollTop = e.detail.scrollTop //滚动的高度// 找到位于顶部元素的索引,距离大于滚动高度的第一个元素的上一个元素就是此时位于顶部的元素let index = this.distanceList.findIndex(it => {// 滚动条的位置大于元素距离顶部位置的距离时,说明元素已经滑过了顶部return (it > scrollTop)}) - 1if (index == this.tabIndex) returnthis.tabIndex = index}, 200)}}}
</script>
<style lang="less" scoped>.main {display: flex;justify-content: space-between;width: 100vw;height: calc(100vh - 44px);}.left-content {width: 250rpx;height: 100%;background-color: #E7E7E7;}.left-item {width: 100%;height: 100rpx;text-align: center;line-height: 100rpx;}.activeItem {background-color: #fff;color: skyblue;}.right-content {flex: 1;height: 100%;background-color: #f4f4f4;}.content-item {width: 100%;height: 200rpx;background-color: aqua;margin-top: 20rpx;}.title {padding: 15px 0 0 10px;}
</style>

大佬

效果

请添加图片描述

代码

<template><view class="bodys"><view class="scroll_box" id="scroll_box"><scroll-view :style="{ height: scrollHeight + 'px' }" scroll-y='true' class="left_box":scroll-into-view="leftIntoView"><view class="left_item" v-for="(item,i) in leftArray" :key='i' @click="onLeft" :data-index="i":id="'left-'+i" :class="{select:i == leftIndex}">{{item}}</view></scroll-view><scroll-view :style="{ height: scrollHeight + 'px' }" @scroll="mainScroll" :scroll-into-view="scrollInto"scroll-y='true' class="right_box" scroll-with-animation="true"><slot></slot><view class="right_item" v-for="(item,i) in rightArray" :key='i' :id="'item-'+i"><view class="rigth_title">{{item.title}}</view><view class="lis" v-for="(items,j) in item.list" :key='j'>{{items}}</view></view><view class="fill-last" :style="{ height: fillHeight + 'px' }"></view></scroll-view></view></view>
</template><script>export default {name: "side-navigation",data() {return {leftArray: [],rightArray: [],scrollHeight: 400,scrollInto: "",leftIndex: 0,topArr: [],scrollTopSize: 0,fillHeight: 0, // 填充高度,用于最后一项低于滚动区域时使用}},computed: {/* 计算左侧滚动位置定位 */leftIntoView() {return `left-${this.leftIndex > 3 ? this.leftIndex - 3 : 0}`;}},mounted() {/* 等待DOM挂载完成 */this.$nextTick(() => {/* 在非H5平台,nextTick回调后有概率获取到错误的元素高度,则添加200ms的延迟来减少BUG的产生 */setTimeout(() => {/* 等待滚动区域初始化完成 */this.initScrollView().then(() => {/* 获取列表数据,你的代码从此处开始 */this.getListData();});}, 200);});},methods: {/* 初始化滚动区域 */initScrollView() {return new Promise((resolve, reject) => {let view = uni.createSelectorQuery().select('#scroll_box');view.boundingClientRect(res => {console.log(res);this.scrollTopSize = res.top;this.scrollHeight = res.height;this.$nextTick(() => {resolve();});}).exec();});},// 获取数据getListData() {new Promise((resolve, reject) => {uni.showLoading();setTimeout(() => {let [left, main] = [[],[]];for (let i = 0; i < 25; i++) {left.push(`${i + 1}类商品`);let list = [];let r = Math.floor(Math.random() * 10);r = r < 1 ? 3 : r;for (let j = 0; j < r; j++) {list.push(j);}main.push({title: `${i + 1}类商品标题`,list});}// 将请求接口返回的数据传递给 Promise 对象的 then 函数。resolve({left,main});}, 1000);}).then(res => {uni.hideLoading();this.leftArray = res.left;this.rightArray = res.main;// DOM 挂载后 再调用 getElementTop 获取高度的方法。this.$nextTick(() => {this.getElementTop();});});},// 获取元素顶部信息getElementTop() {new Promise((resolve, reject) => {let view = uni.createSelectorQuery().selectAll('.right_item');view.boundingClientRect(data => {resolve(data);}).exec();}).then(res => {console.log(res);let topArr = res.map(item => {return item.top - this.scrollTopSize; /* 减去滚动容器距离顶部的距离 */});this.topArr = topArr;/* 获取最后一项的高度,设置填充高度。判断和填充时做了 +-20 的操作,是为了滚动时更好的定位 */let last = res[res.length - 1].height;if (last - 20 < this.scrollHeight) {this.fillHeight = this.scrollHeight - last + 20;}});},// 点击左侧导航onLeft(e) {const index = e.currentTarget.dataset.index;// this.leftIndex = indexthis.scrollInto = `item-${index}`},// 右侧滑动mainScroll(e) {let top = e.detail.scrollTop;let index = 0;/* 查找当前滚动距离 */for (let i = this.topArr.length - 1; i >= 0; i--) {/* 在部分安卓设备上,因手机逻辑分辨率与rpx单位计算不是整数,滚动距离与有误差,增加2px来完善该问题 */if (top + 2 >= this.topArr[i]) {index = i;break;}}this.leftIndex = index < 0 ? 0 : index;},},}
</script><style>page,.bodys {height: 100%;}.scroll_box {display: flex;height: 100%;}.left_box {width: 30%;}.left_item {height: 80rpx;}.lis {height: 200rpx;border-radius: 10rpx;background: #808080;color: #FFFFFF;text-align: center;line-height: 200rpx;margin-bottom: 10rpx;}.select {background-color: #4CD964;}
</style>

Vant-UI官网

网址1

网址2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/88987.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

目标分类笔记(二): 利用PaddleClas的框架来完成多标签分类任务(从数据准备到训练测试部署的完整流程)

文章目录 一、演示多分类效果二、PaddleClas介绍三、代码获取四、数据集获取五、环境搭建六、数据格式分析七、模型训练7.1 模型恢复训练7.2 多卡训练7.3 其他训练指标 八、模型预测九、模型评估十、PaddleClas相关博客 一、演示多分类效果 二、PaddleClas介绍 PaddleClas主要…

Java实现文档格式转换与模板渲染 LibreOffice jodconverter

Java Office 一、文档格式转换 文档格式转换是office操作中经常需要进行一个操作&#xff0c;例如将docx文档转换成pdf格式。 java在这方面有许多的操作方式&#xff0c;大致可以分为内部调用&#xff08;无需要安装额外软件&#xff09;&#xff0c;外部调用&#xff08;需…

【boost网络库从青铜到王者】第七篇:asio网络编程中的异步echo服务器,以应答为主

文章目录 1、简介2、echo模式应答异步服务器2.1、Session会话类2.2、Server类为服务器接收连接的管理类 3、客户端4、隐患5、总结 1、简介 前文已经介绍了异步操作的api&#xff0c;今天写一个简单的异步echo服务器&#xff0c;以应答为主。 2、echo模式应答异步服务器 2.1、…

【钻石OA】1区SCI,无需版面费,仅2个月录用!

重 点 本期推荐 本期小编给大家推荐的是无需版面费的1区农林科学类SCI&#xff08;钻石OA&#xff09;。 目前进展顺利&#xff0c;在WOS数据库中各项指标表现良好&#xff0c;且无预警记录。 领域符合录用率高&#xff0c;1区SCI最快2个月录用&#xff01; 期刊官网系统提…

零距离揭秘绝地求生:玩家最关心的吃鸡要领和细节全攻略!

绝地求生作为当下最火爆的吃鸡游戏&#xff0c;吸引了无数玩家的关注和参与。然而&#xff0c;要成为顶尖的吃鸡玩家&#xff0c;并不简单。在这篇文章中&#xff0c;我们将为你揭露绝地求生玩家最关心的吃鸡要领和细节&#xff0c;为你提供一份全方位的游戏指南&#xff01; 1…

vue内置组件Transition的详解

1. Transition定义 Vue 提供了两个内置组件&#xff0c;可以帮助你制作基于状态变化的过渡和动画&#xff1a; <Transition>会在一个元素或组件进入和离开 DOM 时应用动画。 <TransitionGroup> 会在一个 v-for 列表中的元素或组件被插入&#xff0c;移动&#xff0…

八大排序详解

目录 1.排序的概念及应用 1.1 排序的概念 1.2 排序的应用 1.3 常见的排序算法 2.常见排序算法的实现 2.1 直接插入排序 2.1.1 基本思想 2.1.2 动图解析 2.1.3 排序步骤&#xff08;默认升序&#xff09; 2.1.4 代码实现 2.1.5 特性总结 2.2 希尔排序 2.2.1 基本思…

修改Jenkins主目录

Windows系统上安装了Jenkins后&#xff0c;默认数据目录&#xff0c;也就是工作区目录&#xff0c;即&#xff1a;每次构建的项目数据文件所在目录为&#xff1a; 随着构建项目的增多&#xff0c;一直用这个目录&#xff0c;C盘东西越来越多&#xff0c;电脑就会越来越卡&#…

【链表】排序链表-力扣148题

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

3+单基因泛癌+铜死亡纯生信思路

今天给同学们分享一篇3单基因泛癌铜死亡纯生信思路的生信文章“Systematic pan-cancer analysis identifies SLC31A1 as a biomarker in multiple tumor types”&#xff0c;这篇文章于2023年3月27日发表在BMC Med Genomics 期刊上&#xff0c;影响因子为3.622。 溶质载体家族3…

面试必杀技:Jmeter性能测试攻略大全(第一弹)

前言 性能测试是一个全栈工程师/架构师必会的技能之一&#xff0c;只有学会性能测试&#xff0c;才能根据得到的测试报告进行分析&#xff0c;找到系统性能的瓶颈所在&#xff0c;而这也是优化架构设计中重要的依据。 第一章 测试流程&#xff1a; 需求分析→环境搭建→测试…

【IDEA】idea恢复pom.xml文件显示灰色并带有删除线

通过idea打开spring boot项目后&#xff0c;发现每个服务中的pom.xml文件显示灰色并带有删除线&#xff0c;下面为解决方案 问题截图 解决方案 打开file——settings——build,execution,deployment——Ignored Files&#xff0c;把pom.xml前面的复选框去掉&#xff0c;去掉之…

IPV6知识总结

目录 一、IPV6与IPV4相比改进之处1. “无限“的地址空间2. 层次化的地址结构3. 即插即用4. 简化了报头头部5.保证端到端网络的完整性6.安全性增强7.增强QoS特性 二、IPV6的规则IPV6地址主要分为了三类&#xff1a;单播地址&#xff0c;组播地址&#xff0c;任播地址单播地址组播…

Docker从认识到实践再到底层原理(七)|Docker存储卷

前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量博客汇总 然后就是博主最近最花时间的一个专栏…

浅谈软件测试面试一些常见的问题

一、简历及岗位匹配度 说到简历&#xff0c;其实这一点是很重要但又被很多职场小白忽视的问题。经常有人说我投了很多简历&#xff0c;但是没有公司给我打电话&#xff0c;怎么办&#xff1f; 首先&#xff0c;应该明白的一点&#xff1a;面对求职市场的激烈竞争性&#xff0…

RFID技术引领汽车零部件加工新时代

RFID技术的兴起引领了汽车零部件加工领域的新时代&#xff0c;作为一种利用无线电频率进行自动识别的技术&#xff0c;RFID技术能够快速、准确地识别物体并获取相关数据&#xff0c;在汽车零部件加工中&#xff0c;RFID技术具有重要的应用价值&#xff0c;可以提高生产效率、降…

C++ Primer 类和对象(3)

类和结构体是比较相似&#xff0c;而传统的C的结构体中都是一些数据的类型&#xff0c;类除了有数据之外还有函数。所以可以把类想象成一个具有既有数据又有函数的复合数据类型。 类是一种将抽象转换为用户定义类型的C工具&#xff0c;它将数据表示和操纵数据的方法组合成一个整…

网络安全复习大纲wcf

单选10判断10填空30简答25分析25 选择 &#xff08;1&#xff09;计算机网络安全是指利用计算机网络管理控制和技术措施&#xff0c;保证在网络环境中数据的&#xff08; &#xff09;、完整性、网络服务可用性和可审查性受到保护。 A、保密性 B、抗攻击性 C、网络服务管理性 …

vite跨域proxy设置与开发、生产环境的接口配置,接口在生产环境下,还能使用proxy代理地址吗

文章目录 vite的proxy开发环境设置如果后端没有提供可以替换的/mis等可替换的后缀的处理办法接口如何区分.env.development开发和.env.production生产环境接口在生产环境下&#xff0c;还能使用proxy代理地址吗&#xff1f; vite的proxy开发环境设置 环境&#xff1a; vite 4…

网安新战场:CTF的那些事儿

CTF CTF的前世今生CTF竞赛中的挑战和难题CTF竞赛必备知识CTF竞赛中的技巧与策略&#xff1a; 写在末尾 主页传送门&#xff1a;&#x1f4c0; 传送 CTF的前世今生 CTF&#xff08;Capture The Flag&#xff09;是一种网络安全竞赛&#xff0c;旨在测试参与者解决各种网络安全问…