今日学习内容
热门推荐下转页面
1、定义类型
import type { PageResult, GoodsItem } from './global'/** 热门推荐 */
export type HotResult = {/** id信息 */id: string/** 活动图片 */bannerPicture: string/** 活动标题 */title: string/** 子类选项 */subTypes: SubTypeItem[]
}/** 热门推荐-子类选项 */
export type SubTypeItem = {/** 子类id */id: string/** 子类标题 */title: string/** 子类对应的商品集合 */goodsItems: PageResult<GoodsItem>
}
2、定义接口
import { http } from '@/utils/http'
import type { PageParam } from '@/types/global'
import type { HotResult } from '@/types/hot'type HotParams = PageParam & {/** Tab 项的 id,默认查询全部 Tab 项的第 1 页数据 */subType?: string
}//获取热门推荐通用的接口
export const getHotRecoments = (url: string, data?: HotParams) => {return http<HotResult>({method: 'GET',url,data,})
}
3、HotPanel设置跳转url
<script setup lang="ts">
import type { HotItem } from '@/types/home'//定义props 接收
defineProps<{list: HotItem[]
}>()
</script><template><!-- 推荐专区 --><view class="panel hot"><view class="item" v-for="item in list" :key="item.id"><view class="title"><text class="title-text">{{ item.title }}</text><text class="title-desc">{{ item.alt }}</text></view><navigator hover-class="none" :url="`/pages/hot/hot?type=` + item.type" class="cards"><imagev-for="(i, index) in item.pictures":key="index"class="image"mode="aspectFit":src="i"></image></navigator></view></view>
</template><style lang="scss">
/* 热门推荐 */
.hot {display: flex;flex-wrap: wrap;min-height: 508rpx;margin: 20rpx 20rpx 0;border-radius: 10rpx;background-color: #fff;.title {display: flex;align-items: center;padding: 24rpx 24rpx 0;font-size: 32rpx;color: #262626;position: relative;.title-desc {font-size: 24rpx;color: #7f7f7f;margin-left: 18rpx;}}.item {display: flex;flex-direction: column;width: 50%;height: 254rpx;border-right: 1rpx solid #eee;border-top: 1rpx solid #eee;.title {justify-content: start;}&:nth-child(2n) {border-right: 0 none;}&:nth-child(-n + 2) {border-top: 0 none;}.image {width: 150rpx;height: 150rpx;}}.cards {flex: 1;padding: 15rpx 20rpx;display: flex;justify-content: space-between;align-items: center;}
}
</style>
4、组件代码
<script setup lang="ts">
import { onLoad } from '@dcloudio/uni-app'
import { ref } from 'vue'
import type { SubTypeItem } from '@/types/hot'
import { getHotRecoments } from '@/services/hot'// 热门推荐页 标题和url
const hotMap = [{ type: '1', title: '特惠推荐', url: '/hot/preference' },{ type: '2', title: '爆款推荐', url: '/hot/inVogue' },{ type: '3', title: '一站买全', url: '/hot/oneStop' },{ type: '4', title: '新鲜好物', url: '/hot/new' },
]
// uniapp 获取页面参数
const query = defineProps<{type: string
}>()//查找出当前类型的类型
const currentHot = hotMap.find((item) => item.type === query.type)//动态设置标题
uni.setNavigationBarTitle({ title: currentHot!.title })const bannerPic = ref('')
const subTypes = ref<(SubTypeItem & { finish?: boolean })[]>([])//请求数据
const getHotRecomentsData = async () => {const res = await getHotRecoments(currentHot!.url, {// 技巧:环境变量,开发环境,修改初始页面方便测试分页结束page: import.meta.env.DEV ? 30 : 1,pageSize: 10,})bannerPic.value = res.result.bannerPicturesubTypes.value = res.result.subTypesconsole.log(res.result)
}//高亮
const activeIndex = ref(0)onLoad(() => {getHotRecomentsData()
})const onScrolltolower = async () => {//获取当前列表的listconst currentSubType = subTypes.value[activeIndex.value]//当前页码累加if (currentSubType.goodsItems.page >= currentSubType.goodsItems.pages) {currentSubType.finish = truereturn}currentSubType.goodsItems.page++//调用接口const res = await getHotRecoments(currentHot!.url, {subType: currentSubType.id,page: currentSubType.goodsItems.page,pageSize: 10,})//数组追加currentSubType.goodsItems.items.push(...res.result.subTypes[activeIndex.value].goodsItems.items)console.log(res)
}
</script><template><view class="viewport"><!-- 推荐封面图 --><view class="cover"><image :src="bannerPic"> </image></view><!-- 推荐选项 --><view class="tabs"><textclass="text"@tap="activeIndex = index":class="{ active: index === activeIndex }"v-for="(item, index) in subTypes":key="item.id">{{ item.title }}</text></view><!-- 推荐列表 --><scroll-viewscroll-yclass="scroll-view"v-for="(item, index) in subTypes":key="item.id"v-show="activeIndex === index"@scrolltolower="onScrolltolower"><view class="goods"><navigatorhover-class="none"class="navigator"v-for="goods in item.goodsItems.items":key="goods.id":url="`/pages/goods/goods?id=${goods.id}`"><image class="thumb" :src="goods.picture"></image><view class="name ellipsis">{{ goods.name }}</view><view class="price"><text class="symbol">¥</text><text class="number">{{ goods.price }}</text></view></navigator></view><view class="loading-text"> {{ item.finish ? '已经到底了~~' : '正在加载...' }} </view></scroll-view></view>
</template><style lang="scss">
page {height: 100%;background-color: #f4f4f4;
}.viewport {display: flex;flex-direction: column;height: 100%;padding: 180rpx 0 0;position: relative;
}.cover {width: 750rpx;height: 225rpx;border-radius: 0 0 40rpx 40rpx;overflow: hidden;position: absolute;left: 0;top: 0;
}.scroll-view {flex: 1;
}.tabs {display: flex;justify-content: space-evenly;height: 100rpx;line-height: 90rpx;margin: 0 20rpx;font-size: 28rpx;border-radius: 10rpx;box-shadow: 0 4rpx 5rpx rgba(200, 200, 200, 0.3);color: #333;background-color: #fff;position: relative;z-index: 9;.text {margin: 0 20rpx;position: relative;}.active {&::after {content: '';width: 40rpx;height: 4rpx;transform: translate(-50%);background-color: #27ba9b;position: absolute;left: 50%;bottom: 24rpx;}}
}.goods {display: flex;flex-wrap: wrap;justify-content: space-between;padding: 0 20rpx 20rpx;.navigator {width: 345rpx;padding: 20rpx;margin-top: 20rpx;border-radius: 10rpx;background-color: #fff;}.thumb {width: 305rpx;height: 305rpx;}.name {height: 88rpx;font-size: 26rpx;}.price {line-height: 1;color: #cf4444;font-size: 30rpx;}.symbol {font-size: 70%;}.decimal {font-size: 70%;}
}.loading-text {text-align: center;font-size: 28rpx;color: #666;padding: 20rpx 0 50rpx;
}
</style>
效果图