Browse Source

feat(index): 实现热销商品Tabs粘性布局功能

- 引入Sticky组件实现Tabs吸顶效果
- 添加粘性状态变化回调通知父组件- 动态计算系统状态栏高度作为吸顶阈值-优化Tabs样式在粘性状态下的视觉表现
- 调整商品列表间距以适配新布局- 完善首页Header组件与Tabs粘性状态联动逻辑
- 移除useDidHide中的主题设置调用
- 初始化时设置应用主题配置
dev
科技小王子 3 days ago
parent
commit
af98a3881a
  1. 3
      src/app.ts
  2. 70
      src/pages/index/BestSellers.tsx
  3. 21
      src/pages/index/index.tsx

3
src/app.ts

@ -38,6 +38,8 @@ function App(props: { children: any; }) {
};
// 可以使用所有的 React Hooks
useEffect(() => {
// 设置主题
handleTheme()
// Taro.getSetting:获取用户的当前设置。返回值中只会出现小程序已经向用户请求过的权限。
Taro.getSetting({
success: (res) => {
@ -102,7 +104,6 @@ function App(props: { children: any; }) {
// 对应 onHide
useDidHide(() => {
handleTheme()
})
return props.children

70
src/pages/index/BestSellers.tsx

@ -1,15 +1,16 @@
import {useEffect, useState} from "react";
import {Image, Tabs, Empty} from '@nutui/nutui-react-taro'
import {Image, Tabs, Empty, Sticky} from '@nutui/nutui-react-taro'
import {Share} from '@nutui/icons-react-taro'
import {View, Text} from '@tarojs/components';
import Taro from "@tarojs/taro";
import {ShopGoods} from "@/api/shop/shopGoods/model";
import {pageShopGoods} from "@/api/shop/shopGoods";
const BestSellers = () => {
const BestSellers = (props: {onStickyChange?: (isSticky: boolean) => void}) => {
const [tab1value, setTab1value] = useState<string | number>('0')
const [list, setList] = useState<ShopGoods[]>([])
const [goods, setGoods] = useState<ShopGoods>()
const [stickyStatus, setStickyStatus] = useState<boolean>(false)
const reload = () => {
pageShopGoods({}).then(res => {
@ -48,37 +49,62 @@ const BestSellers = () => {
});
}
// 处理粘性布局状态变化
const onStickyChange = (isSticky: boolean) => {
setStickyStatus(isSticky)
// 通知父组件粘性状态变化
props.onStickyChange?.(isSticky)
console.log('Tabs 粘性状态:', isSticky ? '已固定' : '取消固定')
}
// 获取小程序系统信息
const getSystemInfo = () => {
const systemInfo = Taro.getSystemInfoSync()
// 状态栏高度 + 导航栏高度 (一般为44px)
return (systemInfo.statusBarHeight || 0) + 44
}
useEffect(() => {
reload()
}, [])
// 注意:不在这里配置分享,避免与首页分享冲突
// 商品分享应该在商品详情页处理,首页分享应该分享首页本身
return (
<>
<View className={'py-3'}>
{/* Tabs切换组件 */}
<Tabs
value={tab1value}
className={'w-full mb-4'}
onChange={(value) => {
setTab1value(value)
}}
{/* Tabs粘性布局组件 */}
<Sticky
threshold={getSystemInfo()}
onChange={onStickyChange}
style={{
backgroundColor: 'transparent',
zIndex: 999,
backgroundColor: stickyStatus ? '#ffffff' : 'transparent',
boxShadow: stickyStatus ? '0 2px 8px rgba(0,0,0,0.1)' : 'none',
transition: 'all 0.3s ease'
}}
activeType="smile"
>
<Tabs.TabPane title="今日主推">
</Tabs.TabPane>
<Tabs.TabPane title="即将到期">
</Tabs.TabPane>
<Tabs.TabPane title="活动预告">
</Tabs.TabPane>
</Tabs>
<Tabs
value={tab1value}
className={'w-full'}
onChange={(value) => {
setTab1value(value)
}}
style={{
backgroundColor: 'transparent',
paddingTop: stickyStatus ? '8px' : '0',
paddingBottom: stickyStatus ? '8px' : '0',
}}
activeType="smile"
>
<Tabs.TabPane title="今日主推">
</Tabs.TabPane>
<Tabs.TabPane title="即将到期">
</Tabs.TabPane>
<Tabs.TabPane title="活动预告">
</Tabs.TabPane>
</Tabs>
</Sticky>
<View className={'flex flex-col justify-between items-center rounded-lg px-2'}>
<View className={'flex flex-col justify-between items-center rounded-lg px-2 mt-4'}>
{/* 今日主推 */}
{tab1value == '0' && list?.map((item, index) => {
return (

21
src/pages/index/index.tsx

@ -15,6 +15,8 @@ import './index.scss'
function Home() {
// 吸顶状态
const [stickyStatus, setStickyStatus] = useState<boolean>(false)
// Tabs粘性状态
const [tabsStickyStatus, setTabsStickyStatus] = useState<boolean>(false)
useShareAppMessage(() => {
// 获取当前用户ID,用于生成邀请链接
@ -85,6 +87,11 @@ function Home() {
}
}
// 处理Tabs粘性状态变化
const handleTabsStickyChange = (isSticky: boolean) => {
setTabsStickyStatus(isSticky)
}
const reload = () => {
};
@ -150,13 +157,19 @@ function Home() {
return (
<>
<Sticky threshold={0} onChange={() => onSticky(arguments)}>
<Header stickyStatus={stickyStatus}/>
</Sticky>
{/* Header区域 - 根据Tabs粘性状态决定是否固定 */}
{tabsStickyStatus ? (
<Sticky threshold={0}>
<Header stickyStatus={tabsStickyStatus}/>
</Sticky>
) : (
<Header stickyStatus={tabsStickyStatus}/>
)}
<div className={'flex flex-col mt-12'}>
<Menu/>
<Banner/>
<BestSellers/>
<BestSellers onStickyChange={handleTabsStickyChange}/>
{/*<GoodsList/>*/}
</div>
</>

Loading…
Cancel
Save