UniappDay03

发布于:2025-07-27 ⋅ 阅读:(22) ⋅ 点赞:(0)

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 } 交叉类型,基于原有类型上进行扩展,再作为当前数据类型

  1. 封装通用接口
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,
  })
}
  1. 初始化调用
// 获取热门推荐数据
const getHotRecommendData = async () => {
  const res = await getHotRecommendAPI(currHot!.url)
}
// 页面加载时调用
onLoad(() => {
  getHotRecommendData()
})

3.类型定义

类型的复用

export type GuessItem = GoodsItem


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>
}



type HotParams = PageParams & { subType: string }
export const getHotRecommendAPI = (url: string, data?: HotParams) => {
  return http<HotResult>({
    method: 'GET',
    url,
    data,
  })
}

4.渲染页面和Tab交互
  1. 渲染页面
// 推荐封面图
const bannnerPicture = ref('')
// 推荐选项
const subTypes = ref<SubTypeItem[]>([])
// 获取下标
const activeIndex = ref(0)
// 获取热门推荐数据
const getHotRecommendData = async () => {
  const res = await getHotRecommendAPI(currHot!.url)
  bannnerPicture.value = res.result.bannerPicture
  subTypes.value = res.result.subTypes
}
  1. Tab交互
<text
        v-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-view
      v-for="(item, index) in subTypes"
      :key="item.id"
      v-show="activeIndex === index"
      scroll-y
      class="scroll-view"
    >
      <view class="goods">
        <navigator
          hover-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.分页加载

  1. 滚动触底
  2. 获取当前选项
  3. 当前页码累加
  4. 调用API传参
  5. 当前数据追加

实现效果:

// 滚动触底
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 = true
    return 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.bannerPicture
  subTypes.value = res.result.subTypes
}


// 标志已结束
    currsubTypes.finish = true
    return 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交互

  1. 封装API
import { http } from '@/utils/http'
import { CategoryTopItem } from '@/types/category'

export const getCategoryTopAPI = () => {
  return http<CategoryTopItem[]>({
    method: 'GET',
    url: '/category/top',
  })
}

  1. 初始化调用
// 获取分类列表数据
const getCategoryTopData = async () => {
  const res = await getCategoryTopAPI()
}

// 页面加载时调用
onLoad(() => {
  getHomeBannerData()
  getCategoryTopData()
})
  1. 定义类型
// 获取分类列表数据
const cayegoryList = ref<CategoryTopItem[]>([])
const getCategoryTopData = async () => {
  const res = await getCategoryTopAPI()
  cayegoryList.value = res.result
}

  1. 渲染一级分类
 <scroll-view class="primary" scroll-y>
        <view
          v-for="(item, index) in cayegoryList"
          :key="item.id"
          class="item"
          :class="{ active: index === activeIndex }"
        >
  1. 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>
        <view
          v-for="(item, index) in cayegoryList"
          :key="item.id"
          class="item"
          :class="{ active: index === activeIndex }"
          @tap="activeIndex = index"
        >

9.二级分类和商品渲染

  1. 提取当前二级分类数据
// 提取当前二级分类数据
const subCategoryList = computed(() => {
  return cayegoryList.value[activeIndex.value]?.children || []
})
  1. 渲染二级分类
  2. 渲染商品
 <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">
            <navigator
              v-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>

网站公告

今日签到

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