uniapp+vue3+ts --微信小程序tab导航可以上下滚动选中选项组件代码

uniapp+vue3+ts --微信小程序tab导航可以上下滚动选中选项组件代码

废话不多说,直接上代码。

组件代码:

<template><view class="scroll-tabs-container"><view class="radiusz bg-white pt-[10rpx] z-[999]" :class="{ 'scroll-tabs-sticky': sticky }"><u-tabsid="tabScrollTop"ref="tabScrollTop":list="tabs":current="active"@change="handleChangeTab":active-color="mainColor"bg-color="transparent":bar-width="90"font-size="24":gutter="26"name="title"></u-tabs></view><view class="content"><viewclass="px-[20rpx] pt-[20rpx] pb-[40rpx] w-full bg-white mb-[30rpx] box-border"v-for="(item, index) in tabs":key="item.id":class="'tabs' + index"><view v-if="item.is_show == 1"><view class="text-center"><text class="pr-[10rpx]">———</text>{{ item.title}}<text class="pl-[10rpx]">———</text></view><view class="mt-[40rpx]"><u-parse :html="item.description"></u-parse></view><view class="mt-[40rpx]"><apply-btn:customClass="customClass"btnText=""@popTrue="popTrue"></apply-btn></view></view></view></view></view>
</template><script lang="ts" setup>
const { proxy } = getCurrentInstance() as any
import cache from '@/utils/cache'
import { onShow } from '@dcloudio/uni-app'
/*** @description props参数说明* @property [number] scrollTop 外部传入的滚动条高度* @property [array] tabs tabs* @property [number] current 设置默认的tabIndex* @property [number]  stickyTop 固定定位的高度* @property [boolean] sticky 是否设置tab为固定定位* @property [number] itemOffsetTop 自定义滚动相隔间距,到达会切换tab* @property [object]  tabOptions tab的配置* @property [boolean] scrollTab 滚动时是否切换到指定的tab* @property [boolean] clickScroll 点击时是否滚动到相应位置* @property [number ] duration  滚动持续时长* @property [number] offsetTop 点击滚动到某一模块时的偏离值,每次点击滚动都会减去这个偏离值,这个值的单位是px,*/
const mainColor = ref(cache.get('btnCon').btn_bgColor)
const customClass = ref('m-auto') //按钮样式
const props = defineProps({value: {type: String || Number,default: null},scrollTab: {type: Boolean,default: true},clickScroll: {type: Boolean,default: true},scrollTop: {type: Number || String,default: null},tabs: {type: Array,default: () => [] as any[]},// 设置默认的tabIndexcurrent: {type: Number,default: 0},stickyTop: {type: String,default: null},// 是否将tab设为固定定位sticky: {type: Boolean,default: true},// 自定义间距 ,当 top小于等于这个距离的时候会切换tabitemOffsetTop: {type: Number,default: 60},tabOptions: {type: Object,default: () => ({})},duration: {type: Number,default: 300},offsetTop: {type: Number,default: 0}
})
const tabTopHeight = ref(0)
const active = ref(0)
const click = ref(false)
const timer = ref()
watch([() => props.scrollTop, () => active.value],([newScrollTop, newActive], [oldScrollTop, oldActive]) => {if (newScrollTop) {if (!click.value) {scrollToTab()}}if (newActive != oldActive) {nextTick(() => {scrollToElement()})}},{ immediate: true }
)onMounted(() => {getScrollTabTopHeight()
})
onShow(() => {isPopup.value = false
})
/*** @description: 跳转加盟申请页面* @param {*} isLogin 是否登陆* @return {*}*/
const popTrue = (isLogin: boolean) => {if (!isLogin) {isPopup.value = !isLogin} else {uni.navigateTo({url: linkUrl.value})}
}const getScrollTabTopHeight = async () => {// 获取tab的高度const query = (await createSelectorQueryForThis('#tabScrollTop', false)) as anyif (!query) returntabTopHeight.value = query.height
}const createSelectorQueryForThis = (selector: string, all: any) => {return new Promise((resolve) => {proxy.createSelectorQuery()[all ? 'selectAll' : 'select'](selector).boundingClientRect((rect: any) => {resolve(rect)}).exec()})
}const createSelectorQuery = (selector: any, all: any) => {return new Promise((resolve) => {proxy.createSelectorQuery()[all ? 'selectAll' : 'select'](selector).boundingClientRect((rect: any) => {resolve(rect)}).exec()})
}
const emit = defineEmits<{(event: 'onChange', index: number): void(event: 'input', active: any): void
}>()
const handleChangeTab = (index: any) => {active.value = indexclick.value = true
}
// 点击滑动到指定元素
const scrollToElement = async () => {if (!click.value) return falseconst tab = props.tabs[active.value]if (!tab) returnconst { scroll_id } = tab as anyif (!scroll_id) return falseclearTimeout(timer.value)const queryData = (await createSelectorQuery(`.${scroll_id}`, false)) as anyif (tabTopHeight.value === 0) await getScrollTabTopHeight()if (!queryData) {click.value = truereturn false}let scrollTop = props.scrollTop + queryData.top - props.offsetTopscrollTop -= tabTopHeight.value// 页面滚动函数uni.pageScrollTo({scrollTop,duration: props.duration,success: () => {timer.value = setTimeout(() => {click.value = false}, props.duration + 500)}})
}
const scrollToTab = async () => {if (!props.scrollTab && !click.value) return falseconst length = props.tabs.lengthlet allClass = ''for (let i = 0; i < length; i++) {const { scroll_id } = props.tabs[i] as anyallClass += i < length - 1 ? `.${scroll_id},` : `.${scroll_id}`}const queryData = (await createSelectorQuery(allClass, true)) as anyfor (let i = 0; i < queryData.length; i++) {if (queryData[i].top <= props.itemOffsetTop) {active.value = i}}
}
</script><style lang="scss" scoped>
.scroll-tabs-container {.status_bar {display: none;// height: var(--status-bar-height);}.scroll-tabs-sticky {z-index: 9999;overflow: hidden;-webkit-transform: translateZ(0);transform: translate3d(0, 0, 0);background: white;}
}
.radiusz {border-radius: 26rpx 26rpx 0 0;margin-top: -98rpx;border-bottom: 2px solid #eee;position: fixed;width: 100%;
}
</style>

页面调用代码:

<template><view class="bg-[#F3F4F6] w-full"><scroll-tabs:value="current":tabs="graphicIntroduction":tabOptions="{ label: 'title', activeColor: '#222', barColor: '#ff9f0f' }":offsetTop="180":scrollTop="scrollTop":sticky="true":itemOffsetTop="300 + statusBarHeight":clickScroll="clickScroll"></scroll-tabs></view></template><script lang="ts" setup>
import { getMiniNavigation } from '@/api/shop'
import { onLoad, onPageScroll } from '@dcloudio/uni-app'const bannerImg = ref('')
const graphicIntroduction = ref([]) as any
const current = ref(0) // tab默认索引const scrollTop = ref(0)
const clickScroll = ref(false)
const stickyTop = ref()
const statusBarHeight = ref()
onPageScroll((e: any) => {scrollTop.value = e.scrollTop
})onLoad(() => {getMiniNavigationData()// getHeight()uni.getSystemInfo({success: function (e: any) {stickyTop.value = e.statusBarHeight + 44 + 'px'statusBarHeight.value = e.statusBarHeight}})
})/*** @description: 获取首页轮播图和图文介绍* @return {*}*/
const getMiniNavigationData = async () => {const { data } = await getMiniNavigation({ type: 'plan' })bannerImg.value = data.bannerImgconst list = data.graphicIntroductionlist.forEach((item: any) => {if (item.is_show == 1) {graphicIntroduction.value.push(item)}})graphicIntroduction.value.forEach((item: any, index: number) => {item.scroll_id = `tabs${index}`})
}
</script>

效果图:
在这里插入图片描述

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

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

相关文章

0127-2-Vue深入学习5—Vue-Router路由模式

1、Vue-Router三种路由模式&#xff1a; hash&#xff1a;#️⃣使用URL hash 值来做路由&#xff0c;支持所有路由器&#xff1b;history:&#x1f4d6;依赖HTML5 History API和服务器配置&#xff1b;abstract:⛓支持所有JS运行环境&#xff0c;Node.js服务端&#xff1b; 1.1…

Mybatis-Plus入门

Mybatis-Plus入门 MyBatis-Plus 官网&#xff1a;https://mp.baomidou.com/ 1、简介 MyBatis-Plus (简称 MP) 是一个 MyBatis 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、 提高效率而生。 https://github.com/baomidou/mybatis-p…

数字图像处理(实践篇)三十一 Raw图像数据转为RGB图像实践

目录 1 Raw图像和RGB图像 2 Raw图像的排布方式 3 方案 4 实践 5 其他 1 Raw图像和RGB图像 Raw图片是未经压缩的,没有任何数据损失,Raw图片保留了从图像传感器捕获的每个像素的原始信息,因此可以实现更高的图像质量。

CC++内存管理【非常详细,对新手友好】

文章目录 一、程序内存划分1.基础知识2. 堆栈的区别3. 题目练手 二、C语言中动态内存管理方式三、C中动态内存管理方式1. new/delete操作内置类型2. new/delete操作自定义类型 四、operator new和operator delete函数1. 汇编查看编译器底层调用2. 透过源码分析两个全局函数 五、…

husky结合commitlint审查commit信息

commintlint是一个npm包用来规范化我们的commit信息&#xff0c;当然这个行为的操作时期是在git的commit-msg生命周期期间&#xff0c;这一点当然是有husky来控制&#xff0c;需要注意的是commit-msg作为一个git生命周期会被git commit和git merge行为唤醒&#xff0c;并且可以…

2023年五大顶流国漫公司揭秘:谁是最强王者?

各位动漫迷们&#xff0c;是不是觉得2023年的国漫界特别热闹&#xff1f;没错&#xff0c;经过一年激烈的角逐&#xff0c;国漫界涌现出了五大在制作数量和质量上都遥遥领先的顶流公司&#xff0c;他们各怀绝技&#xff0c;各有千秋&#xff0c;让整个国漫界都热闹非凡&#xf…

防御实验(安全策略,用户认证,NAT综合)

目录 步骤一&#xff1a;了解前提&#xff1a; 1.1 题目要求&#xff1a; 1.2 拓扑搭建&#xff0c;IP地址规划。 步骤二&#xff1a;二层配置 2.1 配置IP地址 2.2 valn配置 步骤三&#xff1a;三层的配置&#xff08;防火墙配置&#xff09; 3.1 IP地址配置 3.2 云配…

【数学建模美赛资料更新】往届数学建模竞赛成品论文分享/2024美赛成品论文预定

数学建模美赛&#xff1a;今天更新的是【2024美赛赛题翻译参考思路代码 成品论文】预定。上述材料才美赛比赛过程中都是限量发放&#xff0c;每个题目大概300~500份哦&#xff0c;所以需要同学们提前预定&#xff0c;先到先得哟~ 在这里奉上数模加油站在往期【数维杯国际赛、m…

【前端web入门第二天】01 html语法实现列表与表格

html语法实现列表与表格 文章目录: 1.列表 1.1 无序列表1.2 有序列表1.3 定义列表 2.表格 2.1 表格基本结构2.2 表格结构标签 写在最前,第二天学习目标: 列表 表格 表单 元素为嵌套关系 1.列表 作用:布局内容排列整齐的区域。 列表分类:无序列表、有序列表、定义列表。 1…

[Vulnhub靶机] DC-1

[Vulnhub靶机] DC-1靶机渗透思路及方法&#xff08;个人分享&#xff09; 靶机下载地址&#xff1a; https://download.vulnhub.com/dc/DC-1.zip 靶机地址&#xff1a;192.168.67.28 攻击机地址&#xff1a;192.168.67.3 一、信息收集 1.使用 arp-scan 命令扫描网段内存活的…

【Leetcode】2865. 美丽塔 I

文章目录 题目思路代码结果 题目 题目链接 给你一个长度为 n 下标从 0 开始的整数数组 maxHeights 。 你的任务是在坐标轴上建 n 座塔。第 i 座塔的下标为 i &#xff0c;高度为 heights[i] 。 如果以下条件满足&#xff0c;我们称这些塔是 美丽 的&#xff1a; 1 < hei…

带延迟的随机逼近方案(Stochastic approximation schemes):在网络和机器学习中的应用

1. 并行队列系统中的动态定价Dynamic pricing 1.1 系统的表述 一个含有并行队列的动态定价系统&#xff0c;该系统中对于每个队列有一个入口收费(entry charge) &#xff0c;且系统运行的目标是保持队列长度接近于某个理想的配置。 这里是这个系统的几个关键假设&#xff1a;…