首页 > 分享 > UniApp + Vue3 实现 Tab 点击滚动定位(微信小程序)

UniApp + Vue3 实现 Tab 点击滚动定位(微信小程序)

在使用 UniApp + Vue3 开发微信小程序时,经常会遇到这样一个需求:

顶部是横向滚动的 Tab,点击某个标题,页面自动滚动到对应内容区域。

今天分享一下我自己实现的完整思路与代码。这个案例是以“水果介绍”为例,实现点击水果名称,自动滚动到对应说明区域。

实现效果

顶部横向滚动 Tab(固定在顶部)

点击某个水果名称

页面平滑滚动到对应内容区域

当前选中 Tab 高亮

实现思路

核心逻辑其实分为三步:

渲染 Tab 和内容列表

获取所有内容区域的 top 位置

点击 Tab 时调用 uni.pageScrollTo 滚动

技术栈

框架:Vue3(script setup 语法)

平台:UniApp

运行端:微信小程序

API:uni.createSelectorQuery() + uni.pageScrollTo()

1️⃣ 数据结构

我们定义一个数组 resultListData:

let resultListData = ref([

{

title: "苹果",

content: "苹果介绍..."

},

{

title: "香蕉",

content: "香蕉介绍..."

}

]);

javascript

运行

每一项:

title → 作为顶部 Tab

content → 作为下面的内容区域

2️⃣ 页面结构

顶部 Tab:

<view class="topTab-con">

<view

class="tabItem"

v-for="(item,index) in resultListData"

@click="pickerResFn(item,index)"

:class="activityIndex == index?'activited': ''"

:key="index"

>

{{item.title}}

</view>

</view>

javascript

运行

内容区域:

<view class="res-item"

v-for="(item,index) in resultListData"

:key="index"

>

<view class="res-card">

<view class="title-con">{{item.title}}</view>

<view class="res-con">{{item.content}}</view>

</view>

</view>

javascript

运行

核心逻辑解析

① 记录每个内容块的位置

我们使用:

uni.createSelectorQuery().selectAll().boundingClientRect()

javascript

运行

获取所有 .res-item 的 top 值。

const sectionTops = ref([]);

const getMyElementFn = () => {

const query = uni.createSelectorQuery();

query

.selectAll(".res-item")

.boundingClientRect(data => {

if (data && data.length) {

sectionTops.value = data.map(item => item.top);

}

})

.exec();

};

javascript

运行

⚠ 为什么要在 nextTick 里执行?

因为必须等 DOM 渲染完成才能获取到真实位置。

onMounted(() => {

nextTick(() => {

getMyElementFn();

});

});

javascript

运行

② 点击 Tab 进行滚动

const pickerResFn = (item, index) => {

activityIndex.value = index;

const targetTop = sectionTops.value[index];

uni.pageScrollTo({

scrollTop: targetTop - 80,

duration: 250

});

};

javascript

运行

为什么要减 80?

因为顶部是固定定位的 Tab,高度会遮挡内容。

.topTab-con {

position: fixed;

top: 0;

height: 160rpx;

}

css

所以需要减去固定头部高度(根据实际情况调整)。

样式关键点

1️⃣ 顶部固定横向滚动

.topTab-con {

position: fixed;

top: 0;

overflow-x: auto;

display: flex;

}

css

2️⃣ 隐藏滚动条

&::-webkit-scrollbar {

display: none;

}

css

3️⃣ 激活状态

.tabItem {

background-color: #f6f6f6;

&.activited {

background-color: #007aff;

color: #ffffff;

}

}

css

实现原理总结

功能使用技术获取元素位置uni.createSelectorQuery()页面滚动uni.pageScrollTo()高亮切换Vue3 响应式 refDOM 完成监听nextTick()

注意事项

1️⃣ 必须等 DOM 渲染完再获取位置

否则拿到的是 undefined

2️⃣ 如果数据是接口异步加载

需要在数据赋值后再重新调用:

nextTick(() => { getMyElementFn(); });

html

最终效果

✔ 横向滑动 Tab
✔ 点击跳转对应内容
✔ 平滑滚动
✔ 当前项高亮

整个实现逻辑清晰,性能也不错,非常适合在内容类页面中使用。

结语

这个功能在实际项目中非常常见,比如:

商品详情页

菜单分类页

文章目录导航

医疗说明页

课程章节跳转

如果你也在使用 UniApp + Vue3 开发微信小程序,这个方案可以直接落地使用。

完整代码如下:
 

<template>

<view class="fruit-page">

<view class="container">

<view class="topTab-con">

<view

class="tabItem"

v-for="(item,index) in resultListData"

@click="pickerResFn(item,index)"

:class="activityIndex == index?'activited': ''"

:key="index"

>{{item.title}}</view>

</view>

<view class="result-content">

<view

class="res-item"

v-for="(item,index) in resultListData"

:key="index"

:id="'section'+index"

>

<view class="res-card">

<view class="title-con">{{item.title}}</view>

<view class="res-con">{{item.content}}</view>

</view>

</view>

</view>

</view>

</view>

</template>

<script setup>

import { ref, onMounted, nextTick } from "vue";

import { onLoad } from "@dcloudio/uni-app";

let resultListData = ref([

{

title: "苹果",

content:

"学名Malus pumila Mill.,别称西洋苹果、柰,属于蔷薇科苹果属的植物。苹果是全球最广泛种植和销售的水果之一,具有悠久的栽培历史和广泛的分布范围。苹果的原始种群主要起源于中亚的天山山脉附近,尤其是现代哈萨克斯坦的阿拉木图地区,提供了所有现代苹果品种的基因库。苹果通过早期的贸易路线,如丝绸之路,从中亚向外扩散到全球各地。"

},

{

title: "香蕉",

content:

"英文名(banana)芭蕉科芭蕉属多年生草本植物,植株丛生,有匐匍茎;假茎浓绿有黑色斑点;叶片长圆形,上面为深绿色,无白粉,下面浅绿色;花朵为乳白色或淡紫色;果实呈弯曲的弓状,有棱,果皮为青绿色,成熟后变黄;果肉松软,黄白色,味甜香味浓,无种子"

},

{

title: "葡萄",

content:

"(学名:Vitis vinifera L.)是葡萄科葡萄属高大缠绕藤本,幼茎秃净或略被绵毛;叶片为纸质,圆卵形或圆形;花序大而长;萼很小,为黄绿色的杯状;花柱很短,为圆锥形;浆果为卵圆形至卵状长圆形,成熟时为紫黑色或红而带青色。 花期4-5月,果期8-9月。 李时珍在《本草纲目》中说:葡萄,《汉书》作蒲桃,可以造酒,人哺饮之,则陶然而醉,故有是名。"

},

{

title: "梨子",

content:

"蔷薇科梨属乔木植物, 树冠开展;小枝粗壮,幼时有柔毛:二年生的枝紫褐色,具稀疏皮孔;托叶膜质,边缘具腺齿;叶片卵形或椭圆形,先端渐尖或急尖,初时两面有绒毛,老叶无毛;伞形总状花序,总花梗和花梗幼时有绒毛;果实卵形或近球形,微扁,褐色;花为白色;花期4月;果期8-9月。种子黑色或黑褐色,种皮软骨质,子叶平凸。"

},

{

title: "量天尺",

content:

"是仙人掌科蛇鞭柱属的攀援肉质灌木,别名火龙果、三角柱、三棱箭、霸王鞭等 。茎粗壮,有常呈翅状的棱,深绿色至淡蓝绿色;小窠沿棱排列,有硬刺。花漏斗状,瓣状花被片白色。浆果红色,长球形,果肉白色。花期7~12月。 "

},

{

title: "杏",

content:

"是蔷薇科李属落叶乔木,高约5-12米 ,别名归勒斯、杏子、野杏树等。杏是落叶乔木,高约8-12米。树冠开阔,呈圆球形或扁球形;叶呈宽卵形或圆卵形;花单生,两性花,花瓣呈白色或带红色;果实球形,白色、黄色至黄红色;种仁味苦或甜。花期3~4月,果期6~7月"

},

{

title: "桃",

content:

"蔷薇科李属落叶小乔木植物;枝条圆柱形,光滑;叶互生,卵状披针形或长圆状披针形,有细齿,托叶线形;花萼被短柔毛,花瓣粉红色;核果宽卵状球形,密被短柔毛;核坚木质;种子扁卵状心形; 花期3-4月,果实成熟期因品种而异,通常为8-9月。"

},

{

title: "樱桃",

content:

"属于乔木,株高达3-8米,树皮红褐色;嫩枝无毛或被疏柔毛;冬芽无毛;叶卵形或长圆状倒卵形,先端渐尖或尾尖,基部圆,有尖锐重锯齿,齿端有小腺体,上面近无毛,下面淡绿色,沿脉或脉间有稀疏柔毛;叶柄被疏柔毛,先端有1或2个大腺体,托叶早落,披针形,有羽裂腺齿;花序伞房状或近伞形,先叶开花;总苞倒卵状椭圆形,花梗被疏柔毛;萼筒钟状,长外面被疏柔毛,萼片三角状卵形或卵状长圆形,全缘,长为萼筒一半或近半;花瓣白色,卵形,先端下凹或2裂;花柱与雄蕊近等长,无毛;核果近球形,熟时红色,可食用。"

},

{

title: "凤梨",

content:

"别名菠萝、露兜子、波罗等,是凤梨科凤梨属一种多年生草本果树。 该植物植株高约1米。茎短粗,呈褐色,基部有吸芽抽出。叶多数,莲座式排列,剑形;穗状花序于叶丛中抽出,状如松球;聚花果球状,果肉黄色多汁;种子细小,质地坚硬,紫黑色,为尖卵形。 花期夏季,果期5-7月。 "

},

{

title: "芒果",

content:

"是漆树科杧果属高大乔木,为热带和亚热带果树。常绿大乔木。树皮灰褐色,小枝褐色,无毛。叶薄革质,略具光泽,常集生枝顶,叶形和大小变化较大,通常为长圆形或长圆状披针形,叶侧脉20-25对,斜升,两面突起,网脉不显,叶柄长2-6厘米,上面具槽,基部膨大。圆锥花序,多花密集,被灰黄色微柔毛,分枝开展,苞片披针形,花小,杂性,黄色或淡黄色,花梗具节,萼片卵状披针形,花瓣长圆形或长圆状披针形,花盘膨大,肉质,雄蕊仅1个发育,花药卵圆形;子房斜卵形。中果皮肉质,肥厚,鲜黄色,味甜。果核坚硬且大,肾形,成熟时黄色"

},

{

title: "草莓",

content:

"为蔷薇科草莓属多年生草本植物 ,又名凤梨草莓,洋莓,红莓等。草莓植株一般高10~40厘米;茎低于叶或近相等;小叶具短柄,倒卵形或菱形,叶柄密被开展黄色柔毛;聚伞花序,花瓣白色,近圆形或倒卵椭圆形;雄蕊20枚,雌蕊极多。聚合果大,呈鲜红色;瘦果尖卵形,光滑 [2]。种子呈螺旋状排列在果肉上,长圆形,黄色或黄绿色。花期4~5月,果期6~7月"

}

]);

let activityIndex = ref(0);

const sectionTops = ref([]);

const pickerResFn = (item, index) => {

activityIndex.value = index;

const targetTop = sectionTops.value[index];

uni.pageScrollTo({

scrollTop: targetTop - 80,

duration: 250

});

};

const getMyElementFn = () => {

const query = uni.createSelectorQuery();

query

.selectAll(".res-item")

.boundingClientRect(data => {

if (data && data.length) {

sectionTops.value = data.map(item => item.top);

} else {

console.log("未找到元素");

}

})

.exec();

};

onMounted(() => {

nextTick(() => {

getMyElementFn();

});

});

onLoad(options => {});

</script>

<style lang="scss">

.fruit-page {

background-color: #ffffff;

min-height: 100vh;

.container {

padding-bottom: 40rpx;

padding-top: 160rpx;

.topTab-con {

position: fixed;

top: 0;

background-color: #ffffff;

height: 160rpx;

width: 100%;

overflow-x: auto;

display: flex;

gap: 12rpx;

padding: 40rpx;

scrollbar-width: none;

-ms-overflow-style: none;

&::-webkit-scrollbar {

display: none;

}

.tabItem {

flex: 0 0 auto;

width: 170rpx;

height: 80rpx;

border-radius: 40rpx;

background-color: #f6f6f6;

color: #383838;

text-align: center;

line-height: 80rpx;

font-size: 24rpx;

&.activited {

background-color: #007aff;

color: #ffffff;

}

}

}

.result-content {

padding: 0 40rpx;

.res-item {

margin-top: 40rpx;

.res-card {

padding: 32rpx;

border-radius: 28rpx;

box-shadow: 0px 0px 2px 0px #171a1f14;

.title-con {

font-size: 36rpx;

font-weight: 700;

}

.res-con {

margin-top: 20rpx;

color: #5f5f5f;

line-height: 46rpx;

font-size: 28rpx;

font-weight: 400;

}

}

}

}

}

}

</style>

html

效果:

相关知识

基于uniapp微信小程序的摄影街拍圈子交流平台
微信小程序鲜花销售小程序+后台管理系统
[花店]网上花店微信小程序的设计与实现
微信商城小程序开发:仅需四步,简单轻松搭建鲜花店商城小程序
Cursor实战回顾:花慧小程序开发
精品Nodejs实现的微信小程序的健康运动饮食减肥管理系统设计与实现源码
微信小程序毕业设计作品成品(44)微信小程序鲜花花店商城系统设计与实现
uniapp+vue3+云开发全栈开发同城配送鲜花小程序任意商城,基础入门到实战,毕设就业【共152课时】
新零售/网店/商城
微信小程序识别花草方法步骤 微信小程序怎么识别花草

网址: UniApp + Vue3 实现 Tab 点击滚动定位(微信小程序) https://m.huajiangbk.com/newsview2566344.html

所属分类:花卉
上一篇: 百年前一个日本人的巴蜀行纪18:
下一篇: 过年的酒与初春的花 | 《吃吃喝