学习笔记 | 微信小程序项目day04

今日学习内容

  • 热门推荐下转页面

热门推荐下转页面

1、定义类型

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

2、定义接口

import { http } from '@/utils/http'
import type { PageParam } from '@/types/global'
import type { HotResult } from '@/types/hot'

type HotParams = PageParam & {
  /** Tab 项的 id,默认查询全部 Tab 项的第 1 页数据 */
  subType?: string
}

//获取热门推荐通用的接口
export const getHotRecoments = (url: string, data?: HotParams) => {
  return http<HotResult>({
    method: 'GET',
    url,
    data,
  })
}

3、HotPanel设置跳转url

<script setup lang="ts">
import type { HotItem } from '@/types/home'

//定义props 接收
defineProps<{
  list: HotItem[]
}>()
</script>

<template>
  <!-- 推荐专区 -->
  <view class="panel hot">
    <view class="item" v-for="item in list" :key="item.id">
      <view class="title">
        <text class="title-text">{{ item.title }}</text>
        <text class="title-desc">{{ item.alt }}</text>
      </view>
      <navigator hover-class="none" :url="`/pages/hot/hot?type=` + item.type" class="cards">
        <image
          v-for="(i, index) in item.pictures"
          :key="index"
          class="image"
          mode="aspectFit"
          :src="i"
        ></image>
      </navigator>
    </view>
  </view>
</template>

<style lang="scss">
/* 热门推荐 */
.hot {
  display: flex;
  flex-wrap: wrap;
  min-height: 508rpx;
  margin: 20rpx 20rpx 0;
  border-radius: 10rpx;
  background-color: #fff;

  .title {
    display: flex;
    align-items: center;
    padding: 24rpx 24rpx 0;
    font-size: 32rpx;
    color: #262626;
    position: relative;

    .title-desc {
      font-size: 24rpx;
      color: #7f7f7f;
      margin-left: 18rpx;
    }
  }

  .item {
    display: flex;
    flex-direction: column;
    width: 50%;
    height: 254rpx;
    border-right: 1rpx solid #eee;
    border-top: 1rpx solid #eee;

    .title {
      justify-content: start;
    }

    &:nth-child(2n) {
      border-right: 0 none;
    }

    &:nth-child(-n + 2) {
      border-top: 0 none;
    }

    .image {
      width: 150rpx;
      height: 150rpx;
    }
  }

  .cards {
    flex: 1;
    padding: 15rpx 20rpx;
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
}
</style>

4、组件代码

<script setup lang="ts">
import { onLoad } from '@dcloudio/uni-app'
import { ref } from 'vue'
import type { SubTypeItem } from '@/types/hot'
import { getHotRecoments } from '@/services/hot'

// 热门推荐页 标题和url
const hotMap = [
  { type: '1', title: '特惠推荐', url: '/hot/preference' },
  { type: '2', title: '爆款推荐', url: '/hot/inVogue' },
  { type: '3', title: '一站买全', url: '/hot/oneStop' },
  { type: '4', title: '新鲜好物', url: '/hot/new' },
]
// uniapp 获取页面参数
const query = defineProps<{
  type: string
}>()

//查找出当前类型的类型
const currentHot = hotMap.find((item) => item.type === query.type)

//动态设置标题
uni.setNavigationBarTitle({ title: currentHot!.title })

const bannerPic = ref('')
const subTypes = ref<(SubTypeItem & { finish?: boolean })[]>([])

//请求数据
const getHotRecomentsData = async () => {
  const res = await getHotRecoments(currentHot!.url, {
    // 技巧:环境变量,开发环境,修改初始页面方便测试分页结束
    page: import.meta.env.DEV ? 30 : 1,
    pageSize: 10,
  })
  bannerPic.value = res.result.bannerPicture
  subTypes.value = res.result.subTypes
  console.log(res.result)
}

//高亮
const activeIndex = ref(0)

onLoad(() => {
  getHotRecomentsData()
})

const onScrolltolower = async () => {
  //获取当前列表的list
  const currentSubType = subTypes.value[activeIndex.value]
  //当前页码累加
  if (currentSubType.goodsItems.page >= currentSubType.goodsItems.pages) {
    currentSubType.finish = true
    return
  }
  currentSubType.goodsItems.page++
  //调用接口
  const res = await getHotRecoments(currentHot!.url, {
    subType: currentSubType.id,
    page: currentSubType.goodsItems.page,
    pageSize: 10,
  })

  //数组追加
  currentSubType.goodsItems.items.push(...res.result.subTypes[activeIndex.value].goodsItems.items)

  console.log(res)
}
</script>

<template>
  <view class="viewport">
    <!-- 推荐封面图 -->
    <view class="cover">
      <image :src="bannerPic"> </image>
    </view>
    <!-- 推荐选项 -->
    <view class="tabs">
      <text
        class="text"
        @tap="activeIndex = index"
        :class="{ active: index === activeIndex }"
        v-for="(item, index) in subTypes"
        :key="item.id"
        >{{ item.title }}</text
      >
    </view>
    <!-- 推荐列表 -->
    <scroll-view
      scroll-y
      class="scroll-view"
      v-for="(item, index) in subTypes"
      :key="item.id"
      v-show="activeIndex === index"
      @scrolltolower="onScrolltolower"
    >
      <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"> {{ item.finish ? '已经到底了~~' : '正在加载...' }} </view>
    </scroll-view>
  </view>
</template>

<style lang="scss">
page {
  height: 100%;
  background-color: #f4f4f4;
}

.viewport {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 180rpx 0 0;
  position: relative;
}

.cover {
  width: 750rpx;
  height: 225rpx;
  border-radius: 0 0 40rpx 40rpx;
  overflow: hidden;
  position: absolute;
  left: 0;
  top: 0;
}

.scroll-view {
  flex: 1;
}

.tabs {
  display: flex;
  justify-content: space-evenly;
  height: 100rpx;
  line-height: 90rpx;
  margin: 0 20rpx;
  font-size: 28rpx;
  border-radius: 10rpx;
  box-shadow: 0 4rpx 5rpx rgba(200, 200, 200, 0.3);
  color: #333;
  background-color: #fff;
  position: relative;
  z-index: 9;

  .text {
    margin: 0 20rpx;
    position: relative;
  }

  .active {
    &::after {
      content: '';
      width: 40rpx;
      height: 4rpx;
      transform: translate(-50%);
      background-color: #27ba9b;
      position: absolute;
      left: 50%;
      bottom: 24rpx;
    }
  }
}

.goods {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  padding: 0 20rpx 20rpx;

  .navigator {
    width: 345rpx;
    padding: 20rpx;
    margin-top: 20rpx;
    border-radius: 10rpx;
    background-color: #fff;
  }

  .thumb {
    width: 305rpx;
    height: 305rpx;
  }

  .name {
    height: 88rpx;
    font-size: 26rpx;
  }

  .price {
    line-height: 1;
    color: #cf4444;
    font-size: 30rpx;
  }

  .symbol {
    font-size: 70%;
  }

  .decimal {
    font-size: 70%;
  }
}

.loading-text {
  text-align: center;
  font-size: 28rpx;
  color: #666;
  padding: 20rpx 0 50rpx;
}
</style>

效果图

相关推荐

  1. 学习笔记 | 程序项目day06

    2024-03-20 05:08:10       22 阅读
  2. 学习笔记 | 程序项目day07

    2024-03-20 05:08:10       19 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-20 05:08:10       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-20 05:08:10       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-20 05:08:10       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-20 05:08:10       18 阅读

热门阅读

  1. 12350安全生产举报热线系统解决方案

    2024-03-20 05:08:10       14 阅读
  2. 字节-安全研究实习生(二面)

    2024-03-20 05:08:10       15 阅读
  3. 掌握C#中的GUI多线程技巧:WinForms和WPF实例详解

    2024-03-20 05:08:10       15 阅读
  4. OpenAI的ChatGPT应对大学会计考试

    2024-03-20 05:08:10       20 阅读
  5. ppt插件构思

    2024-03-20 05:08:10       15 阅读
  6. 富格林:理智做单增加出金盈利

    2024-03-20 05:08:10       17 阅读
  7. AI智能机器人的安装方法搭建电销机器人

    2024-03-20 05:08:10       17 阅读
  8. 共享旅游卡与我们当下的生活关联

    2024-03-20 05:08:10       17 阅读