UniappDay03

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

  2. 初始化调用

    // 获取热门推荐数据
    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
    }

  2. Tab交互

    <text
    v-for="(item, index) in subTypes"
    :key="item.id"
    class="text"
    :class="{ active: index === activeIndex }"
    @tap="activeIndex = index"
    >{{ item.title }}

用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',
    })
    }

  2. 初始化调用

    // 获取分类列表数据
    const getCategoryTopData = async () => {
    const res = await getCategoryTopAPI()
    }

    // 页面加载时调用
    onLoad(() => {
    getHomeBannerData()
    getCategoryTopData()
    })

  3. 定义类型

    // 获取分类列表数据
    const cayegoryList = ref<CategoryTopItem[]>([])
    const getCategoryTopData = async () => {
    const res = await getCategoryTopAPI()
    cayegoryList.value = res.result
    }

  4. 渲染一级分类

  5. Tab交互

    // 获取分类列表数据
    const cayegoryList = ref<CategoryTopItem[]>([])
    const activeIndex = ref(0)
    const getCategoryTopData = async () => {
    const res = await getCategoryTopAPI()
    cayegoryList.value = res.result
    }

9.二级分类和商品渲染

  1. 提取当前二级分类数据

    // 提取当前二级分类数据
    const subCategoryList = computed(() => {
    return cayegoryList.value[activeIndex.value]?.children || []
    })

  2. 渲染二级分类

  3. 渲染商品

    {{ item.name }} 全部 {{ goods.name }} ¥ {{ goods.price }}
相关推荐
用户2136610035724 小时前
VueRouter进阶-动态路由与嵌套路由
前端·vue.js
暴走的小呆20 小时前
Vue 2 中 Object 的变化侦测:从 getter/setter 到 Dep、Watcher、Observer
vue.js
英勇无比的消炎药20 小时前
TinyVue v-auto-tip: 文本超长自动提示的优雅方案
vue.js
时光足迹1 天前
uni-app 视频通话实战:康复师与患者视频问诊的 6 个致命 Bug 与解决方案
android·ios·uni-app
时光足迹1 天前
腾讯云 TRTC UniApp SDK 从入门到上线
前端·vue.js·uni-app
时光足迹1 天前
uni-app 里把加密视频嵌入页面播放?我分析了 4 种方案,只有 1 种接近完美
前端·vue.js·uni-app
时光足迹1 天前
JPush UniApp UTS 插件完全参考手册:API、事件与厂商通道一网打尽
vue.js·ios·uni-app
时光足迹1 天前
极光推送全攻略(下):uni-app 代码实现与 iOS 排查实战
vue.js·ios·uni-app
时光足迹1 天前
极光推送全攻略(上):被iOS证书折磨了三天,我写了一份前端也能看懂的避坑指南
前端·ios·uni-app
疯狂的魔鬼1 天前
一个"懂分寸"的文本省略组件是怎样炼成的
前端·vue.js·设计