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

今日学习内容

  • 配置自定义导航栏
  • 通用轮播组件
  • 通用的轮播图组件完善以及主页调用
  • 分类面板以及热门推荐面板
  • 猜你喜欢模块(分页查询)
  • 首页下拉刷新
  • 首页骨架屏

配置自定义导航栏

1、创建自定义组件

/index/components/CustomNavbar.vue

<script setup lang="ts">
// 获取屏幕边界到安全区域距离
const { safeAreaInsets } = uni.getSystemInfoSync()
</script>

<template>
  <view class="navbar" :style="{ paddingTop: safeAreaInsets?.top + 'px' }">
    <!-- logo文字 -->
    <view class="logo">
      <image class="logo-image" src="@/static/images/logo.png"></image>
      <text class="logo-text">新鲜 · 亲民 · 快捷</text>
    </view>
    <!-- 搜索条 -->
    <view class="search">
      <text class="icon-search">搜索商品</text>
      <text class="icon-scan"></text>
    </view>
  </view>
</template>

<style lang="scss">
/* 自定义导航条 */
.navbar {
  background-image: url(@/static/images/navigator_bg.png);
  background-size: cover;
  position: relative;
  display: flex;
  flex-direction: column;
  padding-top: 20px;

  .logo {
    display: flex;
    align-items: center;
    height: 64rpx;
    padding-left: 30rpx;
    padding-top: 20rpx;

    .logo-image {
      width: 166rpx;
      height: 39rpx;
    }

    .logo-text {
      flex: 1;
      line-height: 28rpx;
      color: #fff;
      margin: 2rpx 0 0 20rpx;
      padding-left: 20rpx;
      border-left: 1rpx solid #fff;
      font-size: 26rpx;
    }
  }

  .search {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 10rpx 0 26rpx;
    height: 64rpx;
    margin: 16rpx 20rpx;
    color: #fff;
    font-size: 28rpx;
    border-radius: 32rpx;
    background-color: rgba(255, 255, 255, 0.5);
  }

  .icon-search {
    &::before {
      margin-right: 10rpx;
    }
  }

  .icon-scan {
    font-size: 30rpx;
    padding: 15rpx;
  }
}
</style>

2、配置隐藏栏样式为自定义

pages.json

    {
      "path": "pages/index/index",
      "style": {
        "navigationStyle": "custom", // 隐藏默认导航
        "navigationBarTextStyle": "white",
        "navigationBarTitleText": "首页"
      }
    },

3、在index中使用

<script setup lang="ts">
import CustomNavbar from './components/CustomNavbar.vue'
</script>


<template>
  <CustomNavbar />
  <uni-card title="基础卡片" sub-title="副标题" extra="额外信息"
    thumbnail="https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png">
    <text>这是一个带头像和双标题的基础卡片,此示例展示了一个完整的卡片。</text>
  </uni-card>
</template>

效果图:

通用轮播组件

配置通用组件自动导入

pages.json文件中配置

"easycom": {
    "autoscan": true,
    "custom": {
      // uni-ui 规则如下配置
      "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue",
      "^Xtx(.*)": "@/components/Xtx$1.vue"
    }
  },

配置类型声明

新建一个ts文件

// src/types/components.d.ts
import XtxSwiper from './XtxSwiper.vue'
declare module 'vue' {
  export interface GlobalComponents {
    XtxSwiper: typeof XtxSwiper
  }
}

轮播组件代码

<script setup lang="ts">
import { ref } from 'vue'

//高亮的
const activeIndex = ref(0)

//当swiper下标发生变化时出发
const onChange: UniHelper.SwiperOnChange = (ev) => {
  // console.log(ev.detail?.current)
  activeIndex.value = ev.detail?.current
}

</script>

<template>
  <view class="carousel">
    <swiper @change="onChange" :circular="true" :autoplay="false" :interval="3000">
      <swiper-item>
        <navigator url="/pages/index/index" hover-class="none" class="navigator">
          <image mode="aspectFill" class="image"
            src="https://pcapi-xiaotuxian-front-devtest.itheima.net/miniapp/uploads/slider_1.jpg"></image>
        </navigator>
      </swiper-item>
      <swiper-item>
        <navigator url="/pages/index/index" hover-class="none" class="navigator">
          <image mode="aspectFill" class="image"
            src="https://pcapi-xiaotuxian-front-devtest.itheima.net/miniapp/uploads/slider_2.jpg"></image>
        </navigator>
      </swiper-item>
      <swiper-item>
        <navigator url="/pages/index/index" hover-class="none" class="navigator">
          <image mode="aspectFill" class="image"
            src="https://pcapi-xiaotuxian-front-devtest.itheima.net/miniapp/uploads/slider_3.jpg"></image>
        </navigator>
      </swiper-item>
    </swiper>
    <!-- 指示点 -->
    <view class="indicator">
      <text v-for="(item, index) in 3" :key="item" class="dot" :class="{ active: index === activeIndex }"></text>
    </view>
  </view>
</template>

<style lang="scss">
/* 轮播图 */
.carousel {
  height: 280rpx;
  position: relative;
  overflow: hidden;
  transform: translateY(0);
  background-color: #efefef;

  .indicator {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 16rpx;
    display: flex;
    justify-content: center;

    .dot {
      width: 30rpx;
      height: 6rpx;
      margin: 0 8rpx;
      border-radius: 6rpx;
      background-color: rgba(255, 255, 255, 0.4);
    }

    .active {
      background-color: #fff;
    }
  }

  .navigator,
  .image {
    width: 100%;
    height: 100%;
  }
}
</style>

通用的轮播图组件完善以及主页调用

1、声明轮播图数据的类型

//轮播图数据类型
export type BannerItem = {

  //跳转连接
  hrefUrl: string

  //id
  id: string

  //图片地址
  imgUrl: string

  //跳转类型
  type: number

}

2、封装接口

import type { BannerItem } from "@/types/home"
import { http } from "@/utils/http"

//首页的广告区域
export const getHomeBannerApi = (distributionSite = 1) => {
  return http<BannerItem[]>({
    url: '/home/banner',
    method: 'GET',
    data: {
      distributionSite
    }
  })
}

3、首页调用

<script setup lang="ts">
import CustomNavbar from './components/CustomNavbar.vue'
import { getHomeBannerApi } from '@/services/home'
import { onLoad } from '@dcloudio/uni-app';
import { ref } from 'vue'
import type { BannerItem } from "@/types/home"


const bannerList = ref<BannerItem[]>([])

//获取轮播图数据
const getHomeBannerData = async () => {
  const res = await getHomeBannerApi()
  bannerList.value = res.result
  console.log(bannerList.value)
}

onLoad(() => {
  getHomeBannerData()
})

</script>

<template>
  <CustomNavbar />
  <XtxSwiper :list="bannerList" />
  <uni-card title="基础卡片" sub-title="副标题" extra="额外信息"
    thumbnail="https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png">
    <text>这是一个带头像和双标题的基础卡片,此示例展示了一个完整的卡片。</text>
  </uni-card>
</template>

<style lang="scss">
//
</style>

4、完善通用组件

<script setup lang="ts">
import type { BannerItem } from '@/types/home';
import { ref } from 'vue'

//高亮的指示点
const activeIndex = ref(0)

//当swiper下标发生变化时出发
const onChange: UniHelper.SwiperOnChange = (ev) => {
  // console.log(ev.detail?.current)
  activeIndex.value = ev.detail!.current
}


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


</script>

<template>
  <view class="carousel">
    <swiper @change="onChange" :circular="true" :autoplay="false" :interval="3000">
      <swiper-item v-for="item in list" :key="item.id">
        <navigator :url="'/pages/index/index/' + item.hrefUrl" 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>

<style lang="scss">
/* 轮播图 */
.carousel {
  height: 280rpx;
  position: relative;
  overflow: hidden;
  transform: translateY(0);
  background-color: #efefef;

  .indicator {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 16rpx;
    display: flex;
    justify-content: center;

    .dot {
      width: 30rpx;
      height: 6rpx;
      margin: 0 8rpx;
      border-radius: 6rpx;
      background-color: rgba(255, 255, 255, 0.4);
    }

    .active {
      background-color: #fff;
    }
  }

  .navigator,
  .image {
    width: 100%;
    height: 100%;
  }
}
</style>

分类面板以及热门推荐面板

1、定义类型


//分类数据类型
export type CategoryItem = {
  //id
  id: string

  //名字
  name: string

  //图标
  icon: string
}


/**
 * 热门推荐数据
 */
export type HotItem = {
  /**
   * 推荐说明
   */
  alt: string,
  /**
   * id
   */
  id: string,
  /**
   * 图片集合
   */
  pictures: string[],
  /**
   * 跳转地址
   */
  target: string,
  /**
   * 推荐标题
   */
  title: string,
  /**
   * 推荐类型
   */
  type: string
}

2、封装接口

//前台分类api
export const getHomeCategoryApi = () => {
  return http<CategoryItem[]>({
    url: '/home/category/mutli',
    method: 'GET',
  })
}

//热门推荐api
export const getHomeHotApi = () => {
  return http<HotItem[]>({
    url: '/home/hot/mutli',
    method: 'GET',
  })
}

3、首页调用

<script setup lang="ts">
import CustomNavbar from './components/CustomNavbar.vue'
import HotPanel from './components/HotPanel.vue'
import { getHomeBannerApi, getHomeCategoryApi, getHomeHotApi } from '@/services/home'
import { onLoad } from '@dcloudio/uni-app'
import { ref } from 'vue'
import type { BannerItem, CategoryItem, HotItem } from '@/types/home'

import CategoryPanel from './components/CategoryPanel.vue'

const bannerList = ref<BannerItem[]>([])
const categoryList = ref<CategoryItem[]>([])
const hotList = ref<HotItem[]>([])

//获取轮播图数据
const getHomeBannerData = async () => {
  const res = await getHomeBannerApi()
  bannerList.value = res.result
}

//获取前台分类数据
const getHomeCategoryData = async () => {
  const res = await getHomeCategoryApi()
  categoryList.value = res.result
}

//获取热门推荐数据
const getHomeHotData = async () => {
  const res = await getHomeHotApi()
  hotList.value = res.result
}

onLoad(() => {
  getHomeBannerData()
  getHomeCategoryData()
  getHomeHotData()
})
</script>

<template>
  <!-- 自定义导航 -->
  <CustomNavbar />
  <!-- 首页轮播图 -->
  <XtxSwiper :list="bannerList" />

  <!-- 前台分类 -->
  <CategoryPanel :list="categoryList" />

  <!-- 热门推荐 -->
  <HotPanel :list="hotList" />
  index
</template>

<style lang="scss">
page {
  background-color: #f7f7f7;
}
</style>

4、组件完善

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

//定义props 接收
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>

<style lang="scss">
/* 前台类目 */
.category {
  margin: 20rpx 0 0;
  padding: 10rpx 0;
  display: flex;
  flex-wrap: wrap;
  min-height: 328rpx;

  .category-item {
    width: 150rpx;
    display: flex;
    justify-content: center;
    flex-direction: column;
    align-items: center;
    box-sizing: border-box;

    .icon {
      width: 100rpx;
      height: 100rpx;
    }

    .text {
      font-size: 26rpx;
      color: #666;
    }
  }
}
</style>
<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" class="cards">
        <image v-for="i in item.pictures" :key="i" 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>

猜你喜欢模块(分页查询)

1、定义类型

组件类型

/**
 * declare module '@vue/runtime-core'
 *   现调整为
 * declare module 'vue'
 */


import XtxSwiper from '@/components/XtxSwiper.vue'
import XtxGuess from '@/components/XtxGuess.vue'

import 'vue'
declare module 'vue' {
  export interface GlobalComponents {
    XtxSwiper: typeof XtxSwiper,
    XtxGuess: typeof XtxGuess
  }
}


//组件实例类型
export type XtxGuessInstance = InstanceType<typeof XtxGuess>

通用分页相关类型


/**
 * 返回数据
 */
export type PageResult<T> = {
  /**
   * 总条数
   */
  counts: number,
  /**
   * 当前页数据
   */
  items: T[],
  /**
   * 当前页数
   */
  page: number,
  /**
   * 总页数
   */
  pages: number,
  /**
   * 每页条数
   */
  pageSize: number
}


//分页查询参数
export type PageParam = {
  page?: number,
  pageSize?: number
}

猜你喜欢item类型


//猜你喜欢item类型
export type GuessItem = {
  /**
   * 商品描述
   */
  desc: string,
  /**
   * 商品折扣
   */
  discount: number,
  /**
   * id
   */
  id: string,
  /**
   * 商品名称
   */
  name: string,
  /**
   * 商品已下单数量
   */
  orderNum: number,
  /**
   * 商品图片
   */
  picture: string,
  /**
   * 商品价格
   */
  price: number
}

2、封装接口

//猜你喜欢
export const getHomeGuessApi = (param: PageParam) => {
  return http<PageResult<GuessItem>>({
    url: '/home/goods/guessLike',
    method: 'GET',
    data: param
  })
}

3、组件代码

<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { getHomeGuessApi } from '@/services/home'
import type { GuessItem } from '@/types/home';
import type { PageParam } from '@/types/global'

const finish = ref(false)

const list = ref<GuessItem[]>([]);
const pageParam: Required<PageParam> = {
  page: 1,
  pageSize: 10
}


const getGuessData = async () => {

  if (finish.value === true) {
    return
  }

  const res = await getHomeGuessApi(pageParam)
  //追加数据
  list.value.push(...res.result.items)
  if (pageParam.page < res.result.pages) {
    //增加pageNo
    pageParam.page++
  } else {
    finish.value = true
  }

}

onMounted(() => {
  getGuessData()
})

defineExpose({
  getMore: getGuessData,
})
</script>

<template>
  <!-- 猜你喜欢 -->
  <view class="caption">
    <text class="text">猜你喜欢</text>
  </view>
  <view class="guess">
    <navigator class="guess-item" v-for="item in list" :key="item.id" :url="`/pages/goods/goods?id=${item.orderNum}`">
      <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"> {{ finish === false ? '正在加载...' : '已经到底了~~' }} </view>
</template>

<style lang="scss">
:host {
  display: block;
}

/* 分类标题 */
.caption {
  display: flex;
  justify-content: center;
  line-height: 1;
  padding: 36rpx 0 40rpx;
  font-size: 32rpx;
  color: #262626;

  .text {
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 0 28rpx 0 30rpx;

    &::before,
    &::after {
      content: '';
      width: 20rpx;
      height: 20rpx;
      background-image: url(@/static/images/bubble.png);
      background-size: contain;
      margin: 0 10rpx;
    }
  }
}

/* 猜你喜欢 */
.guess {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  padding: 0 20rpx;

  .guess-item {
    width: 345rpx;
    padding: 24rpx 20rpx 20rpx;
    margin-bottom: 20rpx;
    border-radius: 10rpx;
    overflow: hidden;
    background-color: #fff;
  }

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

  .name {
    height: 75rpx;
    margin: 10rpx 0;
    font-size: 26rpx;
    color: #262626;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
  }

  .price {
    line-height: 1;
    padding-top: 4rpx;
    color: #cf4444;
    font-size: 26rpx;
  }

  .small {
    font-size: 80%;
  }
}

// 加载提示文字
.loading-text {
  text-align: center;
  font-size: 28rpx;
  color: #666;
  padding: 20rpx 0;
}
</style>

4、首页调用

<script setup lang="ts">
import CustomNavbar from './components/CustomNavbar.vue'
import HotPanel from './components/HotPanel.vue'
import { getHomeBannerApi, getHomeCategoryApi, getHomeHotApi } from '@/services/home'
import { onLoad } from '@dcloudio/uni-app'
import { ref } from 'vue'
import type { BannerItem, CategoryItem, HotItem } from '@/types/home'
import type { XtxGuessInstance } from '@/types/component'

import CategoryPanel from './components/CategoryPanel.vue'

const bannerList = ref<BannerItem[]>([])
const categoryList = ref<CategoryItem[]>([])
const hotList = ref<HotItem[]>([])

//获取轮播图数据
const getHomeBannerData = async () => {
  const res = await getHomeBannerApi()
  bannerList.value = res.result
}

//获取前台分类数据
const getHomeCategoryData = async () => {
  const res = await getHomeCategoryApi()
  categoryList.value = res.result
}

//获取热门推荐数据
const getHomeHotData = async () => {
  const res = await getHomeHotApi()
  hotList.value = res.result
}



onLoad(() => {
  getHomeBannerData()
  getHomeCategoryData()
  getHomeHotData()
})

const guessRef = ref<XtxGuessInstance>()
const onScrolltolower = () => {
  guessRef.value!.getMore()
}
</script>

<template>
  <!-- 自定义导航 -->
  <CustomNavbar />

  <!-- 滚动容器 -->
  <scroll-view class="scroll-view" scroll-y @scrolltolower="onScrolltolower">
    <!-- 首页轮播图 -->
    <XtxSwiper :list="bannerList" />

    <!-- 前台分类 -->
    <CategoryPanel :list="categoryList" />

    <!-- 热门推荐 -->
    <HotPanel :list="hotList" />

    <!-- 猜你喜欢 -->
    <XtxGuess ref="guessRef" />
  </scroll-view>
</template>

<style lang="scss">
page {
  background-color: #f7f7f7;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.scroll-view {
  flex: 1;
}
</style>

首页下拉刷新

<script setup lang="ts">
import CustomNavbar from './components/CustomNavbar.vue'
import HotPanel from './components/HotPanel.vue'
import { getHomeBannerApi, getHomeCategoryApi, getHomeHotApi } from '@/services/home'
import { onLoad } from '@dcloudio/uni-app'
import { ref } from 'vue'
import type { BannerItem, CategoryItem, HotItem } from '@/types/home'
import type { XtxGuessInstance } from '@/types/component'

import CategoryPanel from './components/CategoryPanel.vue'

const bannerList = ref<BannerItem[]>([])
const categoryList = ref<CategoryItem[]>([])
const hotList = ref<HotItem[]>([])

//获取轮播图数据
const getHomeBannerData = async () => {
  const res = await getHomeBannerApi()
  bannerList.value = res.result
}

//获取前台分类数据
const getHomeCategoryData = async () => {
  const res = await getHomeCategoryApi()
  categoryList.value = res.result
}

//获取热门推荐数据
const getHomeHotData = async () => {
  const res = await getHomeHotApi()
  hotList.value = res.result
}

onLoad(() => {
  getHomeBannerData()
  getHomeCategoryData()
  getHomeHotData()
})

const isRefresher = ref(false)

//组件
const guessRef = ref<XtxGuessInstance>()
const onScrolltolower = () => {
  guessRef.value!.getMore()
}

//下拉刷新事件
const onRefresherrefresh = async () => {
  //开启动画
  isRefresher.value = true

  //三个请求同时进行
  await Promise.all([guessRef.value?.clear(), getHomeBannerData(), getHomeCategoryData(), getHomeHotData()])

  //第一次亲求猜你喜欢
  guessRef.value!.getMore()

  //关闭动画
  isRefresher.value = false
}

</script>

<template>
  <!-- 自定义导航 -->
  <CustomNavbar />

  <!-- 滚动容器 -->
  <scroll-view :refresher-triggered="isRefresher" @refresherrefresh="onRefresherrefresh" :refresher-enabled="true"
    class="scroll-view" scroll-y @scrolltolower="onScrolltolower">
    <!-- 首页轮播图 -->
    <XtxSwiper :list="bannerList" />

    <!-- 前台分类 -->
    <CategoryPanel :list="categoryList" />

    <!-- 热门推荐 -->
    <HotPanel :list="hotList" />

    <!-- 猜你喜欢 -->
    <XtxGuess ref="guessRef" />
  </scroll-view>
</template>

<style lang="scss">
page {
  background-color: #f7f7f7;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.scroll-view {
  flex: 1;
}
</style>
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { getHomeGuessApi } from '@/services/home'
import type { GuessItem } from '@/types/home'
import type { PageParam } from '@/types/global'

const finish = ref(false)

const list = ref<GuessItem[]>([])
const pageParam: Required<PageParam> = {
  page: 1,
  pageSize: 10,
}

const getGuessData = async () => {
  if (finish.value === true) {
    return
  }

  const res = await getHomeGuessApi(pageParam)
  //追加数据
  list.value.push(...res.result.items)
  if (pageParam.page < res.result.pages) {
    //增加pageNo
    pageParam.page++
  } else {
    finish.value = true
  }
}

//重置数据接口
const flush = () => {
  finish.value = false
  pageParam.page = 1
  pageParam.pageSize = 10
  list.value = []
}

onMounted(() => {
  getGuessData()
})

defineExpose({
  getMore: getGuessData,
  clear: flush
})
</script>

<template>
  <!-- 猜你喜欢 -->
  <view class="caption">
    <text class="text">猜你喜欢</text>
  </view>
  <view class="guess">
    <navigator class="guess-item" v-for="item in list" :key="item.id" :url="`/pages/goods/goods?id=${item.orderNum}`">
      <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"> {{ finish === false ? '正在加载...' : '已经到底了~~' }} </view>
</template>

<style lang="scss">
:host {
  display: block;
}

/* 分类标题 */
.caption {
  display: flex;
  justify-content: center;
  line-height: 1;
  padding: 36rpx 0 40rpx;
  font-size: 32rpx;
  color: #262626;

  .text {
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 0 28rpx 0 30rpx;

    &::before,
    &::after {
      content: '';
      width: 20rpx;
      height: 20rpx;
      background-image: url(@/static/images/bubble.png);
      background-size: contain;
      margin: 0 10rpx;
    }
  }
}

/* 猜你喜欢 */
.guess {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  padding: 0 20rpx;

  .guess-item {
    width: 345rpx;
    padding: 24rpx 20rpx 20rpx;
    margin-bottom: 20rpx;
    border-radius: 10rpx;
    overflow: hidden;
    background-color: #fff;
  }

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

  .name {
    height: 75rpx;
    margin: 10rpx 0;
    font-size: 26rpx;
    color: #262626;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
  }

  .price {
    line-height: 1;
    padding-top: 4rpx;
    color: #cf4444;
    font-size: 26rpx;
  }

  .small {
    font-size: 80%;
  }
}

// 加载提示文字
.loading-text {
  text-align: center;
  font-size: 28rpx;
  color: #666;
  padding: 20rpx 0;
}
</style>

首页骨架屏

1、生成代码

<script setup lang="ts">

</script>
<template>
  <view is="components/XtxSwiper">
    <view class="carousel XtxSwiper--carousel">
      <swiper :circular="true" :interval="3000" :current="0" :autoplay="false">
        <swiper-item
          style="position: absolute; width: 100%; height: 100%; transform: translate(0%, 0px) translateZ(0px);">
          <navigator class="navigator XtxSwiper--navigator" hover-class="none">
            <image class="image XtxSwiper--image sk-image" mode="aspectFill"></image>
          </navigator>
        </swiper-item>
      </swiper>
      <view class="indicator XtxSwiper--indicator">
        <text class="dot XtxSwiper--dot active XtxSwiper--active"></text>
        <text class="dot XtxSwiper--dot"></text>
        <text class="dot XtxSwiper--dot"></text>
        <text class="dot XtxSwiper--dot"></text>
        <text class="dot XtxSwiper--dot"></text>
      </view>
    </view>
  </view>
  <view is="pages/index/components/CategoryPanel">
    <view class="category CategoryPanel--category">
      <navigator class="category-item CategoryPanel--category-item" hover-class="none">
        <image class="icon CategoryPanel--icon sk-image"></image>
        <text class="text CategoryPanel--text sk-transparent sk-text-14-2857-240 sk-text">居家</text>
      </navigator>
      <navigator class="category-item CategoryPanel--category-item" hover-class="none">
        <image class="icon CategoryPanel--icon sk-image"></image>
        <text class="text CategoryPanel--text sk-transparent sk-text-14-2857-430 sk-text">锦鲤</text>
      </navigator>
      <navigator class="category-item CategoryPanel--category-item" hover-class="none">
        <image class="icon CategoryPanel--icon sk-image"></image>
        <text class="text CategoryPanel--text sk-transparent sk-text-14-2857-543 sk-text">服饰</text>
      </navigator>
      <navigator class="category-item CategoryPanel--category-item" hover-class="none">
        <image class="icon CategoryPanel--icon sk-image"></image>
        <text class="text CategoryPanel--text sk-transparent sk-text-14-2857-124 sk-text">母婴</text>
      </navigator>
      <navigator class="category-item CategoryPanel--category-item" hover-class="none">
        <image class="icon CategoryPanel--icon sk-image"></image>
        <text class="text CategoryPanel--text sk-transparent sk-text-14-2857-822 sk-text">个护</text>
      </navigator>
      <navigator class="category-item CategoryPanel--category-item" hover-class="none">
        <image class="icon CategoryPanel--icon sk-image"></image>
        <text class="text CategoryPanel--text sk-transparent sk-text-14-2857-514 sk-text">严选</text>
      </navigator>
      <navigator class="category-item CategoryPanel--category-item" hover-class="none">
        <image class="icon CategoryPanel--icon sk-image"></image>
        <text class="text CategoryPanel--text sk-transparent sk-text-14-2857-525 sk-text">数码</text>
      </navigator>
      <navigator class="category-item CategoryPanel--category-item" hover-class="none">
        <image class="icon CategoryPanel--icon sk-image"></image>
        <text class="text CategoryPanel--text sk-transparent sk-text-14-2857-717 sk-text">运动</text>
      </navigator>
      <navigator class="category-item CategoryPanel--category-item" hover-class="none">
        <image class="icon CategoryPanel--icon sk-image"></image>
        <text class="text CategoryPanel--text sk-transparent sk-text-14-2857-122 sk-text">杂项</text>
      </navigator>
      <navigator class="category-item CategoryPanel--category-item" hover-class="none">
        <image class="icon CategoryPanel--icon sk-image"></image>
        <text class="text CategoryPanel--text sk-transparent sk-text-14-2857-140 sk-text">品牌</text>
      </navigator>
    </view>
  </view>
  <view is="pages/index/components/HotPanel">
    <view class="panel HotPanel--panel hot HotPanel--hot">
      <view class="item HotPanel--item">
        <view class="title HotPanel--title">
          <text class="title-text HotPanel--title-text sk-transparent sk-text-14-2857-123 sk-text">特惠推荐</text>
          <text class="title-desc HotPanel--title-desc sk-transparent sk-text-14-2857-825 sk-text">精选全攻略</text>
        </view>
        <navigator class="cards HotPanel--cards" hover-class="none">
          <image class="image HotPanel--image sk-image" mode="aspectFit"></image>
          <image class="image HotPanel--image sk-image" mode="aspectFit"></image>
        </navigator>
      </view>
      <view class="item HotPanel--item">
        <view class="title HotPanel--title">
          <text class="title-text HotPanel--title-text sk-transparent sk-text-14-2857-165 sk-text">爆款推荐</text>
          <text class="title-desc HotPanel--title-desc sk-transparent sk-text-14-2857-196 sk-text">最受欢迎</text>
        </view>
        <navigator class="cards HotPanel--cards" hover-class="none">
          <image class="image HotPanel--image sk-image" mode="aspectFit"></image>
          <image class="image HotPanel--image sk-image" mode="aspectFit"></image>
        </navigator>
      </view>
      <view class="item HotPanel--item">
        <view class="title HotPanel--title">
          <text class="title-text HotPanel--title-text sk-transparent sk-text-14-2857-940 sk-text">一站买全</text>
          <text class="title-desc HotPanel--title-desc sk-transparent sk-text-14-2857-59 sk-text">精心优选</text>
        </view>
        <navigator class="cards HotPanel--cards" hover-class="none">
          <image class="image HotPanel--image sk-image" mode="aspectFit"></image>
          <image class="image HotPanel--image sk-image" mode="aspectFit"></image>
        </navigator>
      </view>
      <view class="item HotPanel--item">
        <view class="title HotPanel--title">
          <text class="title-text HotPanel--title-text sk-transparent sk-text-14-2857-210 sk-text">新鲜好物</text>
          <text class="title-desc HotPanel--title-desc sk-transparent sk-text-14-2857-841 sk-text">生活加分项</text>
        </view>
        <navigator class="cards HotPanel--cards" hover-class="none">
          <image class="image HotPanel--image sk-image" mode="aspectFit"></image>
          <image class="image HotPanel--image sk-image" mode="aspectFit"></image>
        </navigator>
      </view>
    </view>
  </view>
</template>


<style setup>
.sk-transparent {
  color: transparent !important;
}

.sk-text-3-5714-320 {
  background-image: linear-gradient(transparent 3.5714%, #EEEEEE 0%, #EEEEEE 96.4286%, transparent 0%) !important;
  background-size: 100% 28.0000rpx;
  position: relative !important;
}

.sk-text {
  background-origin: content-box !important;
  background-clip: content-box !important;
  background-color: transparent !important;
  color: transparent !important;
  background-repeat: repeat-y !important;
}

.sk-text-14-2857-597 {
  background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
  background-size: 100% 39.2000rpx;
  position: relative !important;
}

.sk-text-14-2857-240 {
  background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
  background-size: 100% 36.4000rpx;
  position: relative !important;
}

.sk-text-14-2857-430 {
  background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
  background-size: 100% 36.4000rpx;
  position: relative !important;
}

.sk-text-14-2857-543 {
  background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
  background-size: 100% 36.4000rpx;
  position: relative !important;
}

.sk-text-14-2857-124 {
  background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
  background-size: 100% 36.4000rpx;
  position: relative !important;
}

.sk-text-14-2857-822 {
  background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
  background-size: 100% 36.4000rpx;
  position: relative !important;
}

.sk-text-14-2857-514 {
  background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
  background-size: 100% 36.4000rpx;
  position: relative !important;
}

.sk-text-14-2857-525 {
  background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
  background-size: 100% 36.4000rpx;
  position: relative !important;
}

.sk-text-14-2857-717 {
  background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
  background-size: 100% 36.4000rpx;
  position: relative !important;
}

.sk-text-14-2857-122 {
  background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
  background-size: 100% 36.4000rpx;
  position: relative !important;
}

.sk-text-14-2857-140 {
  background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
  background-size: 100% 36.4000rpx;
  position: relative !important;
}

.sk-text-14-2857-123 {
  background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
  background-size: 100% 44.8000rpx;
  position: relative !important;
}

.sk-text-14-2857-825 {
  background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
  background-size: 100% 33.6000rpx;
  position: relative !important;
}

.sk-text-14-2857-165 {
  background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
  background-size: 100% 44.8000rpx;
  position: relative !important;
}

.sk-text-14-2857-196 {
  background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
  background-size: 100% 33.6000rpx;
  position: relative !important;
}

.sk-text-14-2857-940 {
  background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
  background-size: 100% 44.8000rpx;
  position: relative !important;
}

.sk-text-14-2857-59 {
  background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
  background-size: 100% 33.6000rpx;
  position: relative !important;
}

.sk-text-14-2857-210 {
  background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
  background-size: 100% 44.8000rpx;
  position: relative !important;
}

.sk-text-14-2857-841 {
  background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
  background-size: 100% 33.6000rpx;
  position: relative !important;
}

.sk-image {
  background: #EFEFEF !important;
}

.sk-pseudo::before,
.sk-pseudo::after {
  background: #EFEFEF !important;
  background-image: none !important;
  color: transparent !important;
  border-color: transparent !important;
}

.sk-pseudo-rect::before,
.sk-pseudo-rect::after {
  border-radius: 0 !important;
}

.sk-pseudo-circle::before,
.sk-pseudo-circle::after {
  border-radius: 50% !important;
}

.sk-container {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background-color: transparent;
}
</style>

2、首页使用组件

<script setup lang="ts">
import CustomNavbar from './components/CustomNavbar.vue'
import HotPanel from './components/HotPanel.vue'
import { getHomeBannerApi, getHomeCategoryApi, getHomeHotApi } from '@/services/home'
import { onLoad } from '@dcloudio/uni-app'
import { ref } from 'vue'
import type { BannerItem, CategoryItem, HotItem } from '@/types/home'
import type { XtxGuessInstance } from '@/types/component'

import CategoryPanel from './components/CategoryPanel.vue'
import PageSkeleton from './components/PageSkeleton.vue'


const bannerList = ref<BannerItem[]>([])
const categoryList = ref<CategoryItem[]>([])
const hotList = ref<HotItem[]>([])

//获取轮播图数据
const getHomeBannerData = async () => {
  const res = await getHomeBannerApi()
  bannerList.value = res.result
}

//获取前台分类数据
const getHomeCategoryData = async () => {
  const res = await getHomeCategoryApi()
  categoryList.value = res.result
}

//获取热门推荐数据
const getHomeHotData = async () => {
  const res = await getHomeHotApi()
  hotList.value = res.result
}

const isLoading = ref(false)

onLoad(async () => {
  isLoading.value = true

  await Promise.all([
    getHomeBannerData(),
    getHomeCategoryData(),
    getHomeHotData()
  ])

  isLoading.value = false
})

const isRefresher = ref(false)

//组件
const guessRef = ref<XtxGuessInstance>()
const onScrolltolower = () => {
  guessRef.value!.getMore()
}

//下拉刷新事件
const onRefresherrefresh = async () => {
  //开启动画
  isRefresher.value = true

  //三个请求同时进行
  await Promise.all([
    guessRef.value?.clear(),
    getHomeBannerData(),
    getHomeCategoryData(),
    getHomeHotData(),
  ])

  //第一次亲求猜你喜欢
  guessRef.value!.getMore()

  //关闭动画
  isRefresher.value = false
}
</script>

<template>
  <!-- 自定义导航 -->
  <CustomNavbar />

  <!-- 滚动容器 -->
  <scroll-view :refresher-triggered="isRefresher" @refresherrefresh="onRefresherrefresh" :refresher-enabled="true"
    class="scroll-view" scroll-y @scrolltolower="onScrolltolower">

    <PageSkeleton v-if="isLoading" />
    <template v-else>
      <!-- 首页轮播图 -->
      <XtxSwiper :list="bannerList" />

      <!-- 前台分类 -->
      <CategoryPanel :list="categoryList" />

      <!-- 热门推荐 -->
      <HotPanel :list="hotList" />

      <!-- 猜你喜欢 -->
      <XtxGuess ref="guessRef" />
    </template>
  </scroll-view>
</template>

<style lang="scss">
page {
  background-color: #f7f7f7;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.scroll-view {
  flex: 1;
}
</style>

效果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/484373.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

关于使用TCP-S7协议读写西门子PLC字符串的问题

我们可以使用TCP-S7协议读写西门子PLC&#xff0c; 比如PLC中定义一个String[50] 的地址DB300.20 地址DB300.20 DB块编号为300&#xff0c;偏移量【地址】是30 S7协议是西门子PLC自定义的协议&#xff0c;默认端口102&#xff0c;本质仍然是TCP协议的一种具体实现&#xff…

ForceField Effects

支持HDRP、URP和LWRP 完全可定制和优化的ForceField VFX Pack。我们使所有着色器和材质都非常易于调整,因此您可以非常轻松地创建自己独特的效果。几乎每个参数都可以调整。所有这些效果都适合于每个游戏,无论是风格化还是现实主义的。该软件包还附带一系列颜色渐变,可用于更…

力扣-20 有效的括号详解 Java

目录 1.题目分析 2.基础知识储备 2.1 哈希表 2.2 栈的存取 3. 逻辑概要 4.源码 示例 1.题目分析 为了对比都是从内而外&#xff0c;一个个匹配&#xff0c;全部匹配成功即为有效字符 2.基础知识储备 2.1 哈希表 简单来说&#xff0c;keyvalue存储 &#xff0c;通过key…

ideaSSM 高校公寓交流员管理系统bootstrap开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 idea 开发 SSM 高校公寓交流管理系统是一套完善的信息管理系统&#xff0c;结合SSM框架和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数据库&…

一篇文章搞懂并设计循环队列

目录 1.为什么使用循环队列 2. 循环队列组成 为什么要只使用size-1 个空间存储&#xff1f; 3.循环队列的元素进出 3.1 队尾加入元素 3.2 队头删除元素 3.3 取出队头元素 3.4 取出队尾元素 1.为什么使用循环队列 “假溢出”——》 出队列会空出存储空间&#xff0c;无法…

Gogs - 一款极易搭建的自助 Git 服务

Gogs - 一款极易搭建的自助 Git 服务 1. 使用文档References Gogs https://gogs.io/ https://github.com/gogs/gogs Gogs (/gɑgz/) 项目旨在打造一个以最简便的方式搭建简单、稳定和可扩展的自助 Git 服务。使用 Go 语言开发使得 Gogs 能够通过独立的二进制分发&#xff0c;并…

模拟-算法

文章目录 替换所有的问号提莫攻击Z字形变换外观数列数青蛙 替换所有的问号 算法思路&#xff1a; 从前往后遍历整个字符串&#xff0c;找到问号之后&#xff0c;就遍历 a ~ z 去尝试替换即可。 class Solution {public String modifyString(String s) {char[] ss s.toCharA…

最近公共祖先(LCA)

祖孙询问 给定一棵包含 n 个节点的有根无向树&#xff0c;节点编号互不相同&#xff0c;但不一定是 1∼n。 有 m 个询问&#xff0c;每个询问给出了一对节点的编号 x 和 y&#xff0c;询问 x 与 y 的祖孙关系。 输入格式 输入第一行包括一个整数 表示节点个数&#xff1b; …

基于YOLOv8深度学习的橙子病害智能诊断与防治系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标分类

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

【MySQL】复合查询——基本单表查询、多表查询、自连接、子查询、使用from进行子查询、合并查询

文章目录 MySQL复合查询1. 基本单表查询2. 多表查询3. 自连接4. 子查询4.1 单行子查询4.2 多行子查询4.3 多列子查询4.4 使用from进行子查询 5. 合并查询5.1 union5.2 union all MySQL 复合查询 数据库的复合查询是指在一个查询中结合使用多个查询条件或查询子句&#xff0c;以…

java多线程编程面试题总结

一些最基本的基础知识就不总结了&#xff0c;参考之前写的如下几篇博客&#xff0c;阅读顺序从上到下&#xff0c;依次递进。 java 多线程 多线程概述及其三种创建方式 线程的常用方法 java 线程安全问题 三种线程同步方案 线程通信&#xff08;了解&#xff09; java 线程池…

CSS案例-2.简单版侧边栏练习

效果 知识点 标签显示模式 块级元素 block-level 常见元素:<h1>~<h6>、<p>、<div>、<ul>、<ol>、<li>等。 特点: 独占一行长度、宽度、边距都可以控制宽度默认是容器(父级宽度)的100%是一个容器及盒子,里面可以放行内或者…

spring注解驱动系列--AOP探究二

上篇中记录了AnnotationAwareAspectJAutoProxyCreator的创建以及注册&#xff0c;主要是 1、EnableAspectJAutoProxy 注解会开启AOP功能 2、然后这个注解会往容器中注册一个AnnotationAwareAspectJAutoProxyCreator组件。 3、之后在容器创建过程中&#xff0c;注册后置处理器&a…

【免费】【随机优化】智能配电网的双时间尺度随机优化调度

目录 1 主要内容 2 部分代码 3 部分程序结果 4 下载链接 1 主要内容 该程序为文章《Two-Timescale Stochastic Dispatch of Smart Distribution Grids》的源代码&#xff0c;主要做的是主动配电网的双时间尺度随机优化调度&#xff0c;该模型考虑配电网的高效和安全运行涉及…

【大模型】在VS Code(Visual Studio Code)上安装中文汉化版插件

文章目录 一、下载安装二、配置显示语言&#xff08;一&#xff09;调出即将输入命令的搜索模式&#xff08;二&#xff09;在大于号后面输入&#xff1a;Configure Display Language&#xff08;三&#xff09;重启 三、总结 【运行系统】win 11 【本文解决的问题】 1、英文不…

【JS】如何避免输入中文拼音时触发input事件

现有一段代码&#xff0c;监听input事件。 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" con…

GDC期间LayaAir启动全球化战略

3 月 18 日至 3 月 22 日&#xff0c;一年一度的游戏开发者大会&#xff08;GDC&#xff09;在美国旧金山举行。在此期间&#xff0c;Layabox宣布LayaAir引擎启动全球扩张战略&#xff0c;这标志着引擎将步入快速发展的新阶段。此举旨在利用公司先进的3D引擎技术&#xff0c;将…

mysql体系结构及主要文件

目录 1.mysql体系结构 2.数据库与数据库实例 3.物理存储结构​编辑 4.mysql主要文件 4.1数据库配置文件 4.2错误日志 4.3表结构定义文件 4.4慢查询日志 4.4.1慢查询相关参数 4.4.2慢查询参数默认值 4.4.3my.cnf中设置慢查询参数 4.4.4slow_query_log参数 4.4.…

B端设计:如何让UI组件库成为助力,而不是阻力。

首发2023-09-24 15:42贝格前端工场 Hi&#xff0c;我是大千UI工场&#xff0c;网上的UI组件库琳琅满目&#xff0c;比如elementUI、antdesign、iview等等&#xff0c;甚至很多前端框架&#xff0c;也出了很多UI组件&#xff0c;如若依、Layui、bootstrap等等&#xff0c;作为U…

01.数据归档工具的选择-Percona Toolkit,并centos7.9中安装

1.需求 1.1.在实际的业务使用过程中&#xff0c;我们既要考虑服务器硬件的成本&#xff0c;也要考虑系统的稳定性。所以就有了数据归档的这个业务需求了。我们需要把一些老的数据&#xff0c;比如两年前的数据移出去。增强数据库的性能。 1.2.在进行数据归档的过程中&#xf…