uniapp 左右滑动切换页面并切换tab
实现效果如图

要实现底部内部的左右滑动切换带动上方tab栏的切换,并且下方内容要实现纵向滚动 ,所以需要swiper,swiper-item,scroll-view组合使用
tab栏部分
<view class="tabs"><view class="tab_item" v-for="(item,index) in tabList" :key="index" @click="tabSwitch(item,index)"><view class="tab_name" :class="activeTab==index?'act_name':''">{{item.name}}</view><view class="tab_cover" v-if="activeTab!=index"></view><image v-else :src="getimg('leaderboard_toggle.png')" style="width: 30rpx;height: 11rpx;"></image></view></view>
tab栏点击切换,需要重新调取数据
tabSwitch(item, index) {this.scrollTop = 0this.activeTab = index// this.dataList = []this.getData()},
下方内容部分
<swiper class="data_list" @change="swipeIndex" :current="activeTab":duration="300" previous-margin="0" :style="{ height: (pageHeight-205)+'px' }" :circular="true"><swiper-item v-for="(val,idx) in tabList" :key="idx"><scroll-view v-if="dataList.length>0" scroll-y="true" :style="{ height: (pageHeight-205)+'px' }":scroll-top="scrollTop"><view style="padding-bottom: 100rpx;"><view class="data_item" :class="index*1+1<4?'act_item'+(index*1+1):''"v-for="(item,index) in dataList" :key="index" @click="goDetail(item,index)"><view class="le"><image :src="getimg('Leaderboard_'+(index*1+1)+'.png')" mode="heightFix"style="height: 112rpx;"></image><view class="item_content">{{item.idea_name}}</view></view><view class="like_num">{{item.likecount}}</view></view></view></scroll-view><view v-else class="data_none" :style="{ height: (pageHeight-205)+'px' }"><image :src="getimg('null-page.png')" style="width: 380rpx;height: 380rpx;"></image><view class="nothing">空空如也~</view></view></swiper-item></swiper>
滑动切换,改变上方tab栏状态,并重新调取数据
swipeIndex(e){this.activeTab = e.detail.currentthis.scrollTop = 0this.getData()}
以上即可实现页面左右滑动切换带动tab栏切换
但是,上面这种方式适合tab栏目比较少,内容列表也比较短的情况,如果tab栏项目很多,内容数据也很多,用swiper做切换会很卡顿,这个官方地址也有介绍swiper | uni-app官网
我懒得去研究怎么去优化他,不过这个博主的优化方式很厉害,可以借鉴一下,附上地址:
uni-app swiper数量过多时卡顿优化方案_uniapp swiper卡顿_菜鸟驿站2020的博客-CSDN博客
所以当数据很多时,我使用了touch事件加动画的方式做切换
如图,tab栏选项很多,内容列表数据也很多

tabs部分
<view class="tab_box"><view style="max-width: 600rpx;height:80rpx ;"><u-tabs :list="tabsList" :current="actTab" keyName="category_name" @click="tabSwitch" lineWidth="20"lineHeight="4" lineColor="#000000":activeStyle="{color: '#000000',fontWeight: 'bold',transform: 'scale(1.4)'}":inactiveStyle="{color: '#666666',transform: 'scale(1.2)'}"></u-tabs></view><view class="more" @click="cateShow = true"><image :src="getimg('originality_label.png')" style="width: 50rpx;height: 50rpx;"></image></view></view>
列表部分
<view class="data_list" @touchstart="touchStart" @touchend="touchEnd" :animation="animationData" :style="{ height: (pageHeight-(marginTop*1+65))+'px' }"><scroll-view scroll-y="true" :style="{ height: (pageHeight-(marginTop*1+65))+'px' }"@scrolltolower="getBottom" :lower-threshold="80" :scroll-top="scrollTop"><view v-if="dataList.length>0" style="padding-bottom: 100rpx;"><view class="data_item" v-for="(item,index) in dataList" :key="index"@click="goDetail(item,index)"><view class="data_top"><image :src="getimg('originality_quote.png')" style="width: 64rpx;height: 64rpx;"></image><view class="data_content">{{item.idea_name}}</view><view class="lab_box" v-if="item.tag_list && item.tag_list.length>0"><view class="lab_item" v-for="(val,idx) in item.tag_list" :key="idx">{{val.tag_name}}</view></view><view class="times">{{item.updatetime | getDateDiff}}</view></view><view class="data_bot"><view class="share" @click.stop="goShare(item,index)"><image :src="getimg('share_gray.png')" style="width: 36rpx;height: 36rpx;"></image><view class="share_tt">分享</view></view><view class="infos"><view class="comm"><image :src="getimg('review_gray.png')" style="width: 44rpx;height: 44rpx;"></image><view class="comm_num">{{item.comment_count}}</view></view><view class="comm" @click.stop="addLike(item,index)"><image :src="item.is_like?getimg('like_red.png'):getimg('like_gray.png')"style="width: 44rpx;height: 44rpx;"></image><view class="comm_num">{{item.like_count}}</view></view></view></view></view></view><view v-else class="data_none" :style="'margin-top:'+(marginTop*1+150)+'px;'"><image :src="getimg('null-page.png')" style="width: 380rpx;height: 380rpx;"></image><view class="nothing">空空如也~</view></view></scroll-view></view>
如代码所以,我使用了touchstart,和touchend事件,并且加了:animation="animationData"
data(){return{scrollTop: 0,startX: 0,startY: 0,animationData: {}, // 动画}}
onLoad中需要先创建动画实例
onLoad() {uni.getSystemInfo({success: res => {this.pageHeight = res.windowHeight;}})// #ifdef MP-WEIXINconst systemInfo = wx.getSystemInfoSync();const res = wx.getMenuButtonBoundingClientRect();this.height = (res.top - systemInfo.statusBarHeight) * 2 + res.heightthis.marginTop = this.height + systemInfo.statusBarHeight// #endif// 创建动画实例this.animation = uni.createAnimation({timingFunction: 'ease',duration: 120})},
touchend结束事件中计算手指滑动距离,判断滑动方向并重新调用接口加载数据,并且在判断完滑动方向之后加动效,不让左右滑动看起来生硬
touchStart(event) {this.startX = event.touches[0].pageX;this.startY = event.touches[0].pageY;},touchEnd(event) {let deltaX = event.changedTouches[0].pageX - this.startX; let deltaY = event.changedTouches[0].pageY - this.startY;if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX)>60) {if (deltaX < 0) { //往左if (this.actTab == this.tabsList.length - 1) {this.actTab = 0} else {this.actTab = this.actTab * 1 + 1}this.cate_id = this.tabsList[this.actTab].id// 动画:左出右进this.animation.translateX('-100%').step().opacity(0).step({duration: 10}).translateX('100%').step({duration: 10}).translateX(0).opacity(1).step()this.animationData = this.animation.export()setTimeout(() => {this.animationData = {}}, 250)this.dataList = []this.page = 1this.getData()this.goJust() //scrollTop改为0} else if (deltaX > 0) { //往右if (this.actTab == 0) {this.actTab = this.tabsList.length - 1} else {this.actTab = this.actTab * 1 - 1}this.cate_id = this.tabsList[this.actTab].id// 动画:右出左进this.animation.translateX('100%').step() //先横向向右移至100%,即整块移没.opacity(0).step({ //再使滑块部分透明duration: 10}).translateX('-100%').step({ //然后趁透明横向向左移至-100%duration: 10}).translateX(0).opacity(1).step() //接着横向向右移动至初始位置并恢复透明度this.animationData = this.animation.export()// 为避免uniapp动画只有第一次生效,必须延迟删除动画实例数据setTimeout(() => {this.animationData = {}}, 250)this.dataList = []this.page = 1this.getData()this.goJust() //scrollTop改为0} else { // 挪动距离0}}else{}},
最后一步,因为内容包裹在scroll-view里,所以触底加载下一页写在scroll-view的触底事件里@scrolltolower="getBottom"
getBottom() {if (this.page < this.last_page) {this.page += 1this.getData()}},
相关文章:
uniapp 左右滑动切换页面并切换tab
实现效果如图 要实现底部内部的左右滑动切换带动上方tab栏的切换,并且下方内容要实现纵向滚动 ,所以需要swiper,swiper-item,scroll-view组合使用 tab栏部分 <view class"tabs"><view class"tab_item" v-for&…...
FinClip 支持小程序维度域名配置;桌面端体验活动进行中
FinClip 的使命是使您(业务专家和开发人员)能够通过小程序解决关键业务流程挑战,并完成数字化转型的相关操作。不妨让我们看看在本月的产品与市场发布亮点,看看是否有助于您实现目标。 产品方面的相关动向👇…...
已有公司将ChatGPT集成到客服中心以增强用户体验
Ozonetel正在利用ChatGPT来改善客户体验。该公司表示,他们通过使用ChatGPT收集与客户互动过程收集的“语料”能够更有针对性地提高服务效率,提供个性化的用户体验,并实现更高的客户满意度。[1] 通过这套解决方案,客服中心将拥有一…...
108. 将有序数组转换为二叉搜索树
文章目录 题目描述思路解答(c)结果 题目描述 给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二…...
视频分辨率: UXGA/SVGA/VGA/QVGA/QQVGA
视频分辨率除了常见的720p/2K/4K外, 还有VGA系列的分辨率 相关字段含义: V——Video (视频) G——Graphics(图像) A——Array(阵列) S——Super(超级) X——Extended(扩展) U——Ultra(终极) W——Wide&am…...
Leecode力扣27数组移除元素
题目链接:力扣 最终可运行的代码1:暴力法 class Solution { public:int removeElement(vector<int>& nums, int val) {int index0;int numnums.size();while(index<nums.size()-1){if(nums[index]val){int jindex;num--;while(j<nums.…...
百度云盘发展历程与影响
摘要: 百度云盘作为中国领先的云存储与共享服务提供商,自其创立至今经历了多个阶段的发展与变革。本论文通过对百度云盘的历史回顾与分析,探讨了其在技术、商业模式、用户体验以及对社会的影响等方面的演变。同时,还分析了在竞争激…...
SpringBoot复习:(33)WebMvcAutoconfiguration内部静态类WebMvcAutoConfigurationAdapter
WebMvcAutoconfiguration内部静态类WebMvcAutoConfigurationAdapter实现了WebMvcConfigurer接口,重写了一些方法,也就是默认对Spring Mvc进行了一些配置: 该静态类上有个**Import**注解: Import(EnableWebMvcConfiguration.class) 它的父类…...
f1tenth仿真2
起点(0.192,0.201) 终点(9.902,5.148) 起点(9.902,5.148) 终点(-13.289,7.058) 起点(-13.289,7.058) 终点(-13.289,0.201) 起点(-13.289,0.201) #! /usr/bin/env python import time from numba import jit import math import rospy import numpy as…...
exec族函数
本节学习exec族函数,并大量参考了以下链接: linux进程---exec族函数(execl, execlp, execle, execv, execvp, execvpe)_云英的博客-CSDN博客 exec族函数函数的作用 我们用fork函数创建新进程后,经常会在新进程中调用exec函数去执行另外一个程…...
dbm与mw转换
功率值10^(dBm值/10),单位mW。 对于-5dBm,其功率值为0.3162 mW。 dBm 10 * lg(mW)...
【Linux】多线程之单例模式
多线程之单例模式 什么是设计模式,都有哪些设计模式单例模式饿汉模式懒汉模式 什么是设计模式,都有哪些设计模式 设计模式就是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理…...
Vision Transformer模型入门
Vision Transformer模型入门 一、Vision Transformer 模型1,Embedding 层结构详解2,Transformer Encoder 详解3,MLP Head 详解 二、ViT-B/16 网络结构三、Hybrid 模型详解四、ViT 模型搭建参数 一、Vision Transformer 模型 总体三个模块&am…...
如何使用 Go 获取 URL 的参数,以及使用时的问题
Go 获取 URL 参数也很容易,但是由于 Go 有严格的数据类型和错误管理,所以在使用时会些微有些复杂。所以本文不仅会讲如何获取 URL 的参数,也会讲在使用时的一些问题。 首先假设 URL 是https://www.example.com/?keywordabc&id12。 其他…...
Linux驱动-基于QT控制LED灯
Linux驱动-基于QT控制LED灯 环境搭建LED驱动程序基于总线设备模型基于设备树 QT界面编程测试 环境搭建 平台 韦东山100ask imax6ull pro && 大象嵌入式开发板Build Root 使用Build root编译image,具体配置可参考《嵌入式Linux应用开发完全手册-IMX6ULL开发…...
布隆过滤器的原理和应用场景
目录 1 原理 2 代码示例 3 位数组 4 布隆过滤器的实际应用场景 1 原理 布隆过滤器(Bloom Filter)是一种数据结构,用于快速判断一个元素是否存在于一个集合中,具有高效的插入和查询操作。它的设计目的是在空间效率和查询效率之…...
ElasticSearch学习
一,简介 ES(elaticsearch简写), Elasticsearch是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据…...
软件测试基础篇——Redis
Redis Redis数据库的配置与连接 解压redis数据库的安装包(建议把解压后的安装包放到磁盘的根目录,方便访问操作)打开【命令行窗口】:winR在命令行窗口,进入到redis安装目录中 格式一:cd /d redis目录…...
大数据扫盲(1): 数据仓库与ETL的关系及ETL工具推荐
在数字化时代,数据成为了企业决策的关键支持。然而,随着数据不断增长,有效地管理和利用这些数据变得至关重要。数据仓库和ETL工具作为数据管理和分析的核心,将帮助企业从庞杂的数据中提取有价值信息。 一、ETL是什么? …...
spring的aop动态代理对象注入时机
bean生命周期: bean实例化populateBean填充属性invokeAwareMethods调用aware方法postProcessBeforeInitialization后置处理器before方法initializeBean初始化beanpostProcessAfterAfterInitialization后置处理器after方法 代理对象注入有两种情况:提前和…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...
接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
