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(() => {
<template> <CustomNavbarom /> <XtxSwiper /> <view class="index">index</view> </template> <style lang="scss"> // </style>
getHomeBannerData()
})
</script>
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) => {
<script setup lang="ts"> import { BannerItem } from '@/types/home' import { ref } from 'vue'
return http<BannerItem[]>({
method: 'GET',
url: '/home/banner',
data: {
distributionSite,
},
})
}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"> <text v-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<{
<template> <view class="category"> <navigator class="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>
list: CategoryItem[]
}>()
</script>
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',
})
} -
传递给子组件并渲染
// 获取热门推荐数据
<script setup lang="ts"> import { CategoryItem } from '@/types/home'
const hotList = ref<HotItem[]>([])
const getHomeHotData = async () => {
const res = await getHomeHotAPI()
hotList.value = res.result
}defineProps<{
<template> <view class="category"> <navigator class="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>
list: CategoryItem[]
}>()
</script>
9.猜你喜欢-组件封装
-
准备组件(通用组件)
-
定义组件类型
import XtxSwiper from '../components/XtxSwiper.vue'
import XtxGuess from '../components/XtxGuess.vue'
declare module '@vue/runtime-core' {
export interface GlobalComponents {
// 确认类型,全局定义
XtxSwiper: typeof XtxSwiper
XtxGuess: 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 = () => {
<script setup lang="ts"> import { getHomeGoodsGuessLikeAPI } from '@/services/home' import { GuessItem } from '@/types/home' import { onMounted } from 'vue' import { ref } from 'vue'
return http<PageResult<GuessItem>>({
method: 'GET',
url: '/home/goods/guessLike',
})
}// 猜你喜欢的列表
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"> <navigator class="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-view
refresher-enabled
@refresherrefresh="onRefreshrefresh"
:refresher-triggered="isTriggered"
@scrolltolower="onScrolltoLower"
class="scroll-view"
scroll-y
>
加载数据
// 自定义下拉刷新
const onRefreshrefresh = async () => {
isTriggered.value = true
getHomeBannerData()
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 = 1
geussList.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 = true
await Promise.all([getHomeBannerData(), getHomeCategoryData(), getHomeHotData()])
isLoading.value = false
})