uni-appDay02

发布于:2025-07-29 ⋅ 阅读:(12) ⋅ 点赞:(0)
1.首页-通用轮播组件

轮播图组件需要再首页和分类页使用,封装成通用组件

  1. 准备组件
  2. 自动导入组件
<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>

  1. 添加组件类型声明
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.轮播图-获取轮播图数据
  1. 封装获取轮播图数据API
import { http } from '@/utils/http'

export const getHomeBannerAPI = (distributionSite = 1) => {
  return http({
    method: 'GET',
    url: '/home/banner',
    data: {
      distributionSite,
    },
  })
}
  1. 页面初始化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.首页-轮播图数据类型并渲染
  1. 定义轮播图数据类型
/** 首页-广告区域数据类型 */
export type BannerItem = {
  /** 跳转链接 */
  hrefUrl: string
  /** id */
  id: string
  /** 图片链接 */
  imgUrl: string
  /** 跳转类型 */
  type: number
}
  1. 指定类型并传值给子组件
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>
  1. 渲染数据
<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.前台分类-组件封装
  1. 准备组件(只有首页使用)
  2. 导入并使用组件
  3. 设置首页底色为#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.前台分类数据
  1. 封装获取前台分类数据API
export const getHomeCategoryAPI = () => {
  return http({
    method: 'GET',
    url: '/home/category/mutli',
  })
}

  1. 页面初始化调用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.前台分类数据类型并渲染
  1. 定义前台分类数据类型
export const getHomeCategoryAPI = () => {
  return http<CategoryItem[]>({
    method: 'GET',
    url: '/home/category/mutli',
  })
}
  1. 指定类型并传值给子组件
const categoryList = ref<CategoryItem[]>([])
const getHomeCategoryData = async () => {
  const res = await getHomeCategoryAPI()
  categoryList.value = res.result
}
  1. 渲染前台分类数据
<script setup lang="ts">
import { CategoryItem } from '@/types/home'

defineProps<{
  list: CategoryItem[]
}>()
</script>

<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>
8.首页-热门推荐
  1. 准备组件(只有首页使用)
  2. 导入并使用组件
  3. 封装获取热门推荐数据API
export const getHomeHotAPI = () => {
  return http({
    method: 'GET',
    url: '/home/hot/mutli',
  })
}
  1. 定义热门推荐数据类型并指定
/** 首页-热门推荐数据类型 */
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',
  })
}
  1. 传递给子组件并渲染
// 获取热门推荐数据
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">
    <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>
9.猜你喜欢-组件封装
  1. 准备组件(通用组件)
  2. 定义组件类型
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
  }
}
  1. 准备scroll-view滚动容器
<template>
  <!-- 自定义导航栏 -->
  <CustomNavbarom />
  <scroll-view class="scroll-view" scroll-y>
    <!-- 自定义轮播图 -->
    <XtxSwiper :list="bannerList" />
    <!-- 分类面板 -->
    <CategoryPanel :list="categoryList" />
    <!-- 热门推荐 -->
    <HotPanel :list="hotList" />
    <!-- 猜你喜欢 -->
    <XtxGuess />
  </scroll-view>
</template>
  1. 设置page和scroll-view样式
<style lang="scss">
page {
  background-color: #f7f7f7;
  height: 100%;
  display: flex;
  flex-direction: column;
}
.scroll-view {
  flex: 1;
}
</style>
10.获取猜你喜欢数据
  1. 封装获取猜你喜欢数据API
export const getHomeGoodsGuessLikeAPI = () => {
  return http({
    method: 'GET',
    url: '/home/goods/guessLike',
  })
}
  1. 组件挂载完毕调用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.猜你喜欢-类型定义和列表渲染
  1. 定义:
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>
  1. 渲染:
<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
})

网站公告

今日签到

点亮在社区的每一天
去签到