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

news/2024/7/20 1:43:01 标签: uni-app, 小程序

今日学习内容

  • 热门推荐下转页面

热门推荐下转页面

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>

效果图


http://www.niftyadmin.cn/n/5439749.html

相关文章

密码学——传统加密技术和公钥加密

传统加密技术和公开密钥 传统加密技术基本概念基本原理公开密钥基本概念基本原理传统加密技术 传统加密,即对称加密或称之为单钥加密,是公钥加密技术出现之前的主流加密技术,甚至在现在,仍然具有广泛应用。 基本概念 回顾一下一些基本概念: 明文,原始的消息和数据,也…

婴儿洗衣机硬核测评:希亦、鲸立、小吉婴儿洗衣机性能大比拼!

如果你非常注重婴儿衣物的卫生问题&#xff0c;那么婴儿洗衣机则是非常理想的选择。毕竟&#xff0c;在婴儿吃奶或者接触其他材料时&#xff0c;其抵抗力是比较弱的&#xff0c;再加上普通洗衣机无法对婴儿的衣物进行有效的消毒处理&#xff0c;轻则会对婴儿的健康造成威胁&…

Linux 查看防火墙相关命令

1、查看防火墙状态 systemctl status firewalld 2、启动防火墙 systemctl start/restart firewalld 3、停止防火墙 临时停用&#xff0c;重启后失效 systemctl stop firewalld 4、永久停止防火墙 systemctl disable firewalld 5、开机启动 systemctl enable firew…

vue2 vue3 diff算法比较

目录 1&#xff1a;没key 补充1&#xff1a;为什么不建议用index作为key值&#xff1f; 2&#xff1a;有key 2.1&#xff1a;vue2diff 2.2&#xff1a;vue3diff 补充2&#xff1a;vue3的最长递增子序列 补充3&#xff1a;vue2diff和vue3diff的比较 补充4&#xff1a;虚…

【开发环境搭建篇】Redis服务器端安装和配置

作者介绍&#xff1a;本人笔名姑苏老陈&#xff0c;从事JAVA开发工作十多年了&#xff0c;带过大学刚毕业的实习生&#xff0c;也带过技术团队。最近有个朋友的表弟&#xff0c;马上要大学毕业了&#xff0c;想从事JAVA开发工作&#xff0c;但不知道从何处入手。于是&#xff0…

设计模式(结构型设计模式——代理模式)

设计模式&#xff08;结构型设计模式——代理模式&#xff09; 代理模式 基本定义 代理模式就是给一个对象提供一个代理&#xff0c;并由代理对象控制对原对象的引用。在代理模式中&#xff0c;“第三者”代理主要是起到一个中介的作用&#xff0c;它连接客户端和目标对象。 …

发布镜像到阿里云仓库

发布上一篇Dockerfile实战-自定义的centos镜像。 1、登录阿里云 2、找到容器镜像服务 3、创建命令空间 4、创建镜像仓库 5、点击进入这个镜像仓库&#xff0c;可以看到所有的信息 6、根据操作指南测试推送发布 6.1登录阿里云 [rootzhoujunru home]# docker login --usernam…

第五章 Collections

第五章 Collections 5.1 常用功能 java.utils.Collections是集合工具类&#xff0c;用来对集合进行操作。部分方法如下&#xff1a; public static <T> boolean addAll(Collection<T> c, T... elements) :往集合中添加一些元素。public static void shuffle(Lis…