1.熱門推薦-準備工作
// 用defineProps獲取頁面參數,query
const query = defineProps<{type: string
}>()
const currHot = hotMap.find((v) => v.type === query.type)
// 動態設置標題
uni.setNavigationBarTitle({ title: currHot!.title })
</script>
2.獲取熱門推薦數據
PageParams & { subType: string } 交叉類型,基于原有類型上進行擴展,再作為當前數據類型
- 封裝通用接口
import type { PageParams } from '@/types/global'
import { http } from '@/utils/http'// 拓展類型
type HotParams = PageParams & { subType: string }
export const getHotRecommendAPI = (url: string, data: HotParams) => {return http({method: 'GET',url,data,})
}
- 初始化調用
// 獲取熱門推薦數據
const getHotRecommendData = async () => {const res = await getHotRecommendAPI(currHot!.url)
}
// 頁面加載時調用
onLoad(() => {getHotRecommendData()
})
3.類型定義
類型的復用
export type GuessItem = GoodsItemimport 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>
}type HotParams = PageParams & { subType: string }
export const getHotRecommendAPI = (url: string, data?: HotParams) => {return http<HotResult>({method: 'GET',url,data,})
}
4.渲染頁面和Tab交互
- 渲染頁面
// 推薦封面圖
const bannnerPicture = ref('')
// 推薦選項
const subTypes = ref<SubTypeItem[]>([])
// 獲取下標
const activeIndex = ref(0)
// 獲取熱門推薦數據
const getHotRecommendData = async () => {const res = await getHotRecommendAPI(currHot!.url)bannnerPicture.value = res.result.bannerPicturesubTypes.value = res.result.subTypes
}
- Tab交互
<textv-for="(item, index) in subTypes":key="item.id"class="text":class="{ active: index === activeIndex }"@tap="activeIndex = index">{{ item.title }}</text>
用v-show反復的切換更好而不用v-if 耗費性能
<!-- 推薦列表 --><scroll-viewv-for="(item, index) in subTypes":key="item.id"v-show="activeIndex === index"scroll-yclass="scroll-view"><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">正在加載...</view></scroll-view></view>
</template>
5.分頁加載
- 滾動觸底
- 獲取當前選項
- 當前頁碼累加
- 調用API傳參
- 當前數據追加
實現效果:
// 滾動觸底
const onScrolltolower = async () => {//獲取當前選項const currsubTypes = subTypes.value[activeIndex.value]// 當前頁碼累加currsubTypes.goodsItems.page++// 調用API傳參const res = await getHotRecommendAPI(currHot!.url, {subType: currsubTypes.id,page: currsubTypes.goodsItems.page,pageSize: currsubTypes.goodsItems.pageSize,})// 新的列表選項const newSubTypes = res.result.subTypes[activeIndex.value]// 數組追加currsubTypes.goodsItems.items.push(...newSubTypes.goodsItems.items)
}
6.分頁結束條件
分頁條件
// 分頁條件if (currsubTypes.goodsItems.page < currsubTypes.goodsItems.pages) {// 當前頁碼累加currsubTypes.goodsItems.page++} else {// 標志已結束currsubTypes.finish = truereturn uni.showToast({ title: '已經到底了' })}
標記已結束
修改一下:
// 給SubTypeItem 再加一個類型,可有可無加?
const subTypes = ref<(SubTypeItem & { finish?: boolean })[]>([])// 獲取熱門推薦數據
const getHotRecommendData = async () => {const res = await getHotRecommendAPI(currHot!.url, {subType: '912000341',// 技巧: 環境變量,開發環境,修改初始頁面方便測試分頁結果page: import.meta.env.DEV ? 30 : 1,pageSize: 10,})bannnerPicture.value = res.result.bannerPicturesubTypes.value = res.result.subTypes
}// 標志已結束currsubTypes.finish = truereturn uni.showToast({ title: '已經到底了' })
頁面底部提示
<view class="loading-text">{{ item.finish ? '已經到底了' : '正在加載中...' }}</view>
技巧:
環境變量,開發環境,修改初始頁面方便測試分頁結果
page: import.meta.env.DEV ? 30 : 1,
7.準備工作
靜態數據=>獲取輪播圖數據=>渲染輪播圖
<script setup lang="ts">
import { getHomeBannerAPI } from '@/services/home'
import { BannerItem } from '@/types/home'
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
const bannerList = ref<BannerItem[]>([])
//獲取輪播圖數據
const getHomeBannerData = async () => {const res = await getHomeBannerAPI()
}
// 頁面加載時調用
onLoad(() => {getHomeBannerData()
})
</script>
8.渲染一級分類和Tab交互
- 封裝API
import { http } from '@/utils/http'
import { CategoryTopItem } from '@/types/category'export const getCategoryTopAPI = () => {return http<CategoryTopItem[]>({method: 'GET',url: '/category/top',})
}
- 初始化調用
// 獲取分類列表數據
const getCategoryTopData = async () => {const res = await getCategoryTopAPI()
}// 頁面加載時調用
onLoad(() => {getHomeBannerData()getCategoryTopData()
})
- 定義類型
// 獲取分類列表數據
const cayegoryList = ref<CategoryTopItem[]>([])
const getCategoryTopData = async () => {const res = await getCategoryTopAPI()cayegoryList.value = res.result
}
- 渲染一級分類
<scroll-view class="primary" scroll-y><viewv-for="(item, index) in cayegoryList":key="item.id"class="item":class="{ active: index === activeIndex }">
- Tab交互
// 獲取分類列表數據
const cayegoryList = ref<CategoryTopItem[]>([])
const activeIndex = ref(0)
const getCategoryTopData = async () => {const res = await getCategoryTopAPI()cayegoryList.value = res.result
}<scroll-view class="primary" scroll-y><viewv-for="(item, index) in cayegoryList":key="item.id"class="item":class="{ active: index === activeIndex }"@tap="activeIndex = index">
9.二級分類和商品渲染
- 提取當前二級分類數據
// 提取當前二級分類數據
const subCategoryList = computed(() => {return cayegoryList.value[activeIndex.value]?.children || []
})
- 渲染二級分類
- 渲染商品
<view class="panel" v-for="item in subCategoryList" :key="item.id"><view class="title"><text class="name">{{ item.name }}</text><navigator class="more" hover-class="none">全部</navigator></view><view class="section"><navigatorv-for="goods in item.goods":key="goods.id"class="goods"hover-class="none":url="`/pages/goods/goods?id=${goods.id}`"><image class="image" :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>