1.首頁-通用輪播組件
輪播圖組件需要再首頁和分類頁使用,封裝成通用組件
- 準備組件
- 自動導入組件
<script setup lang="ts">
import XtxSwiper from '@/components/XtxSwiper.vue'
import CustomNavbar from './components/CustomNavbar.vue'
</script><template><CustomNavbarom /><XtxSwiper /><view class="index">index</view>
</template><style lang="scss">
//
</style>
- 添加組件類型聲明
import XtxSwiper from './XtxSwiper.vue'
declare module '@vue/runtime-core' {export interface GlobalComponents {// 確認類型,全局定義XtxSwiper: typeof XtxSwiper}
}
2.輪播圖-指示點
@change=“onChange”
<script setup lang="ts">
import { ref } from 'vue'const activeIndex = ref(0)
// 當swiper下標變化時觸發
const onChange: UniHelper.SwiperOnChange = (ev) => {// 非空斷言用!. 主觀上排除掉空值情況activeIndex.value = ev.detail!.current
}
</script>
3.輪播圖-獲取輪播圖數據
- 封裝獲取輪播圖數據API
import { http } from '@/utils/http'export const getHomeBannerAPI = (distributionSite = 1) => {return http({method: 'GET',url: '/home/banner',data: {distributionSite,},})
}
- 頁面初始化API
<script setup lang="ts">
import XtxSwiper from '@/components/XtxSwiper.vue'
import { getHomeBannerAPI } from '@/services/home'
import CustomNavbar from './components/CustomNavbar.vue'
import { onLoad } from '@dcloudio/uni-app'const bannerList = ref([])
const getHomeBannerData = async () => {const res = await getHomeBannerAPI()bannerList.value = res.result
}onLoad(() => {getHomeBannerData()
})
</script><template><CustomNavbarom /><XtxSwiper /><view class="index">index</view>
</template><style lang="scss">
//
</style>
4.首頁-輪播圖數據類型并渲染
- 定義輪播圖數據類型
/** 首頁-廣告區域數據類型 */
export type BannerItem = {/** 跳轉鏈接 */hrefUrl: string/** id */id: string/** 圖片鏈接 */imgUrl: string/** 跳轉類型 */type: number
}
- 指定類型并傳值給子組件
import { http } from '@/utils/http'
import { BannerItem } from '@/types/home'export const getHomeBannerAPI = (distributionSite = 1) => {return http<BannerItem[]>({method: 'GET',url: '/home/banner',data: {distributionSite,},})
}<script setup lang="ts">
import { BannerItem } from '@/types/home'
import { ref } from 'vue'const activeIndex = ref(0)
// 當swiper下標變化時觸發
const onChange: UniHelper.SwiperOnChange = (ev) => {// 非空斷言用!. 主觀上排除掉空值情況activeIndex.value = ev.detail!.current
}
defineProps<{list: BannerItem[]
}>()
</script>
- 渲染數據
<template><view class="carousel"><swiper :circular="true" :autoplay="false" :interval="3000" @change="onChange"><swiper-item v-for="item in list" :key="item.id"><navigator url="/pages/index/index" hover-class="none" class="navigator"><image mode="aspectFill" class="image" :src="item.imgUrl"></image></navigator></swiper-item></swiper><!-- 指示點 --><view class="indicator"><textv-for="(item, index) in list":key="item.id"class="dot":class="{ active: index === activeIndex }"></text></view></view>
</template>
5.前臺分類-組件封裝
- 準備組件(只有首頁使用)
- 導入并使用組件
- 設置首頁底色為#F7F7F7
// 導入
<script setup lang="ts">
import CategoryPanel from './components/CategoryPanel.vue'
</script><template><!-- 分類面板 --><CategoryPanel /><view class="index">index</view>
</template><style lang="scss">
page {background-color: #f7f7f7;
}
</style>
6.前臺分類數據
- 封裝獲取前臺分類數據API
export const getHomeCategoryAPI = () => {return http({method: 'GET',url: '/home/category/mutli',})
}
- 頁面初始化調用API
<script setup lang="ts">
import XtxSwiper from '@/components/XtxSwiper.vue'
import { getHomeBannerAPI, getHomeCategoryAPI } from '@/services/home'
import CustomNavbar from './components/CustomNavbar.vue'
import { onLoad } from '@dcloudio/uni-app'
import { ref } from 'vue'
import type { BannerItem } from '@/types/home'
import CategoryPanel from './components/CategoryPanel.vue'// 獲取輪播圖數據
const bannerList = ref<BannerItem[]>([])
const getHomeBannerData = async () => {const res = await getHomeBannerAPI()bannerList.value = res.result
}const getHomeCategoryData = async () => {const res = await getHomeCategoryAPI()
}
// 頁面加載
onLoad(() => {getHomeBannerData()getHomeCategoryData()
})
</script>
7.前臺分類數據類型并渲染
- 定義前臺分類數據類型
export const getHomeCategoryAPI = () => {return http<CategoryItem[]>({method: 'GET',url: '/home/category/mutli',})
}
- 指定類型并傳值給子組件
const categoryList = ref<CategoryItem[]>([])
const getHomeCategoryData = async () => {const res = await getHomeCategoryAPI()categoryList.value = res.result
}
- 渲染前臺分類數據
<script setup lang="ts">
import { CategoryItem } from '@/types/home'defineProps<{list: CategoryItem[]
}>()
</script><template><view class="category"><navigatorclass="category-item"hover-class="none"url="/pages/index/index"v-for="item in list":key="item.id"><image class="icon" :src="item.icon"></image><text class="text">{{ item.name }}</text></navigator></view>
</template>
8.首頁-熱門推薦
- 準備組件(只有首頁使用)
- 導入并使用組件
- 封裝獲取熱門推薦數據API
export const getHomeHotAPI = () => {return http({method: 'GET',url: '/home/hot/mutli',})
}
- 定義熱門推薦數據類型并指定
/** 首頁-熱門推薦數據類型 */
export type HotItem = {/** 說明 */alt: string/** id */id: string/** 圖片集合[ 圖片路徑 ] */pictures: string[]/** 跳轉地址 */target: string/** 標題 */title: string/** 推薦類型 */type: string
}export const getHomeHotAPI = () => {return http<HotItem[]>({method: 'GET',url: '/home/hot/mutli',})
}
- 傳遞給子組件并渲染
// 獲取熱門推薦數據
const hotList = ref<HotItem[]>([])
const getHomeHotData = async () => {const res = await getHomeHotAPI()hotList.value = res.result
}<script setup lang="ts">
import { CategoryItem } from '@/types/home'defineProps<{list: CategoryItem[]
}>()
</script><template><view class="category"><navigatorclass="category-item"hover-class="none"url="/pages/index/index"v-for="item in list":key="item.id"><image class="icon" :src="item.icon"></image><text class="text">{{ item.name }}</text></navigator></view>
</template>
9.猜你喜歡-組件封裝
- 準備組件(通用組件)
- 定義組件類型
import XtxSwiper from '../components/XtxSwiper.vue'
import XtxGuess from '../components/XtxGuess.vue'
declare module '@vue/runtime-core' {export interface GlobalComponents {// 確認類型,全局定義XtxSwiper: typeof XtxSwiperXtxGuess: typeof XtxGuess}
}
- 準備scroll-view滾動容器
<template><!-- 自定義導航欄 --><CustomNavbarom /><scroll-view class="scroll-view" scroll-y><!-- 自定義輪播圖 --><XtxSwiper :list="bannerList" /><!-- 分類面板 --><CategoryPanel :list="categoryList" /><!-- 熱門推薦 --><HotPanel :list="hotList" /><!-- 猜你喜歡 --><XtxGuess /></scroll-view>
</template>
- 設置page和scroll-view樣式
<style lang="scss">
page {background-color: #f7f7f7;height: 100%;display: flex;flex-direction: column;
}
.scroll-view {flex: 1;
}
</style>
10.獲取猜你喜歡數據
- 封裝獲取猜你喜歡數據API
export const getHomeGoodsGuessLikeAPI = () => {return http({method: 'GET',url: '/home/goods/guessLike',})
}
- 組件掛載完畢調用API
<script setup lang="ts">
import { getHomeGoodsGuessLikeAPI } from '@/services/home'
import { onMounted } from 'vue'
//獲取猜你喜歡數據
const getHomeGoodsGuessLikeData = async () => {const res = await getHomeGoodsGuessLikeAPI()
}
// 頁面掛載完成后調用
onMounted(() => {getHomeGoodsGuessLikeData()
})
</script>
11.猜你喜歡-類型定義和列表渲染
- 定義:
export const getHomeGoodsGuessLikeAPI = () => {return http<PageResult<GuessItem>>({method: 'GET',url: '/home/goods/guessLike',})
}<script setup lang="ts">
import { getHomeGoodsGuessLikeAPI } from '@/services/home'
import { GuessItem } from '@/types/home'
import { onMounted } from 'vue'
import { ref } from 'vue'// 猜你喜歡的列表
const geussList = ref<GuessItem[]>([])
//獲取猜你喜歡數據
const getHomeGoodsGuessLikeData = async () => {const res = await getHomeGoodsGuessLikeAPI()geussList.value = res.result.items
}
// 頁面掛載完成后調用
onMounted(() => {getHomeGoodsGuessLikeData()
})
</script>
- 渲染:
<template><!-- 猜你喜歡 --><view class="caption"><text class="text">猜你喜歡</text></view><view class="guess"><navigatorclass="guess-item"v-for="item in geussList":key="item.id":url="`/pages/goods/goods?id=4007498`"><image class="image" mode="aspectFill" :src="item.picture"></image><view class="name"> {{ item.name }} </view><view class="price"><text class="small">¥</text><text>{{ item.price }}</text></view></navigator></view><view class="loading-text"> 正在加載... </view>
</template>
12.分頁準備
監聽事件
<template><!-- 自定義導航欄 --><CustomNavbarom /><!-- 滾動 --><scroll-view @scrolltolower="onScrolltoLower" class="scroll-view" scroll-y><!-- 自定義輪播圖 --><XtxSwiper :list="bannerList" /><!-- 分類面板 --><CategoryPanel :list="categoryList" /><!-- 熱門推薦 --><HotPanel :list="hotList" /><!-- 猜你喜歡 --><XtxGuess ref="GuessRef" /></scroll-view>
</template>
模板ref
const GuessRef = ref<XtxGuessInstance>()
const onScrolltoLower = () => {GuessRef.value?.getMore()
}寫模板類型
export type XtxGuessInstance = InstanceType<typeof XtxGuess>
暴露方法
// 暴露出來
defineExpose({getMore: getHomeGoodsGuessLikeData,
})const onScrolltoLower = () => {
// 調用GuessRef.value?.getMore()
}
13.猜你喜歡分頁加載
在頁碼累加的時候要注意排除掉undefine的情況。將可選轉換為必選
export const getHomeGoodsGuessLikeAPI = (data?: PageParams) => {return http<PageResult<GuessItem>>({method: 'GET',url: '/home/goods/guessLike',data,})
}//分頁參數
//將可選換為必選
const pageParams: Required<PageParams> = {page: 1,pageSize: 10,
}
// 猜你喜歡的列表
const geussList = ref<GuessItem[]>([])
//獲取猜你喜歡數據
const getHomeGoodsGuessLikeData = async () => {const res = await getHomeGoodsGuessLikeAPI()// geussList.value = res.result.items// 數據追加// 要將原數組解構,再追加geussList.value.push(...res.result.items)// 頁碼追加pageParams.page++
}
14.猜你喜歡分頁條件
//分頁參數
//將可選換為必選
const pageParams: Required<PageParams> = {page: 30,pageSize: 10,
}
// 猜你喜歡的列表
const geussList = ref<GuessItem[]>([])
// 已結束標記
const finish = ref(false)
//獲取猜你喜歡數據
const getHomeGoodsGuessLikeData = async () => {// 退出判斷if (finish.value === true) {return wx.showToast({ icon: 'none', title: '沒有更多數據~' })}const res = await getHomeGoodsGuessLikeAPI()// geussList.value = res.result.items// 數據追加geussList.value.push(...res.result.items)// 頁碼小于頁總數if (pageParams.page < res.result.pages) {// 頁碼追加pageParams.page++} else {// =賦值 ===比較finish.value = true}
}
15.首頁-下拉刷新
開啟下拉刷新,監聽事件
<!-- 滾動 --><scroll-viewrefresher-enabled@refresherrefresh="onRefreshrefresh":refresher-triggered="isTriggered"@scrolltolower="onScrolltoLower"class="scroll-view"scroll-y>
加載數據
// 自定義下拉刷新
const onRefreshrefresh = async () => {isTriggered.value = truegetHomeBannerData()getHomeCategoryData()getHomeHotData()
關閉動畫
// 當前下拉刷新狀態
const isTriggered = ref(false)
// 自定義下拉刷新
const onRefreshrefresh = async () => {isTriggered.value = true// getHomeBannerData()// getHomeCategoryData()// getHomeHotData()// 同時請求await Promise.all([getHomeBannerData(), getHomeCategoryData(), getHomeHotData()])// 關閉動畫isTriggered.value = false
}
16.下拉刷新-猜你喜歡組件
重置數據, 暴露出來
// 重置數據
const resetData = () => {pageParams.page = 1geussList.value = []finish.value = false
}
// 暴露出來
defineExpose({resetData,getMore: getHomeGoodsGuessLikeData,
})
重置后調用
// 自定義下拉刷新
const onRefreshrefresh = async () => {isTriggered.value = true// 重置猜你喜歡組件GuessRef.value?.resetData()// getHomeBannerData()// getHomeCategoryData()// getHomeHotData()// 同時請求// 重置后調用await Promise.all([getHomeBannerData(),getHomeCategoryData(),getHomeHotData(),GuessRef.value?.getMore(),])// 關閉動畫isTriggered.value = false
}
17.骨架屏
//template<PageSkeleon v-if="isLoading" /><template v-else><!-- 自定義輪播圖 --><XtxSwiper :list="bannerList" /><!-- 分類面板 --><CategoryPanel :list="categoryList" /><!-- 熱門推薦 --><HotPanel :list="hotList" /><!-- 猜你喜歡 --><XtxGuess ref="GuessRef" /></template></scroll-view>//script
const isLoading = ref(false)
// 頁面加載
onLoad(async () => {isLoading.value = trueawait Promise.all([getHomeBannerData(), getHomeCategoryData(), getHomeHotData()])isLoading.value = false
})