乐意购项目前端开发 #5

发布时间:2024年01月23日

一、二级页面基础分类组件

拆分组件结构

创建组件

以 Cheap.vue为例, Hot.vue 和 New.vue的方法一样

配置路由

在router/index.js中添加路由配置

import { createRouter, createWebHashHistory } from 'vue-router'
import Layout from '@/views/Layout/index.vue'
import Login from '@/views/Login/index.vue'
import Home from '@/views/Home/index.vue'
import SubCategory from '@/views/SubCategory/index.vue'

const routes = [
  {
    // Home 页面是首页下的二级页面,所以要配置在首页路径下
    path: '/',
    component: Layout,
    children: [
      {
        // Home 页默认在首页显示,所以 path 为空
        path: '',
        component: Home,
      },
      {
        path: '/category/cheap',
        component: () => import('@/views/Category/Cheap.vue')
      },
      {
        path: '/category/hot',
        component: () => import('@/views/Category/Hot.vue')
      },
      {
        path: '/category/new',
        component: () => import('@/views/Category/New.vue')
      }
    ]
  },
  {
    path: '/login',
    component: Login
  }
]
const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router

封装接口

在cheap.js中封装新的接口

import http from '@/utils/http'

export function getCheapAPI (data) {
  return http({
    url: '/goods/cheap/category/list',
    method: 'POST',
    data,
  })
}

export function getHomeCheapAPI () {
  return http({
    url: '/goods/cheap/list',
    method: 'get',
  })
}

编写代码

<script setup>
import { getBannerAPI } from "@/api/home/banner";
import { onMounted, ref } from "vue";
import { getCheapAPI } from "@/api/home/cheap";
// import {Page} from "./component/page.vue"
//
const bannerList = ref([]);
// 发送请求
const getBanner = async () => {
  const res = await getBannerAPI();
  console.log(res);
  bannerList.value = res.data;
};

const cheapList = ref([]);

const goodTotal = ref([]);
// 获取基础列表数据
const reqData = ref({
  page: 1,
  pageSize: 12,
});

const getCheapList = async () => {
  const res = await getCheapAPI(reqData.value);
  console.log(res);
  cheapList.value = res.data.list;
  goodTotal.value = res.data.total;
  reqData.value.pageSize =res.data.pageSize
};
// 实现分页切换页面
const handleCurrentChange = (page) => {
  reqData.value.page = page;
  getCheapList();
}
// 实现选择页面展示商品数量
const handleSizeChange = (pageSize) => {
  reqData.value.pageSize = pageSize;
  getCheapList();
}


onMounted(() => {
  getBanner(), getCheapList();
});
console.log(bannerList);
</script>

<template>
  <div class="wrap">
    <!-- banner部分 -->
    <div class="banner">
      <div class="category-banner">
        <!-- 使用ElmentPlus的轮播图组件 -->
        <el-carousel height="450px">
          <!-- 遍历bannerList获取数据 -->
          <el-carousel-item v-for="item in bannerList" :key="item.id">
            <img
              class="banner-img"
              :src="require(`@/assets/img/${item.img1}.jpg`)"
              alt=""
            />
          </el-carousel-item>
        </el-carousel>
      </div>
    </div>
    <!-- 商品展示部分 -->
    <div class="goods">
      <ul class="goods-list">
        <li class="goods-li" v-for="item in cheapList" :key="item.id">
          <RouterLink to="/">
            <img
              class="goods-img"
              :src="require(`@/assets/img/${item.picture1}.jpg`)"
              :alt="item.alt"
            />
            <!-- 名字 -->
            <p class="name">{{ item.goodsName }}</p>
            <!-- 原价 -->
            <p class="origin-price">&yen;{{ item.originalPrice }}</p>
            <!-- 现价 -->
            <p class="price">&yen;{{ item.price }}</p>
          </RouterLink>
        </li>
      </ul>
    </div>
    <!-- 分页部分 -->
    <div class="page">
      <!-- <el-pagination  class="pagination" background layout="prev, pager, next" :total="1000">
      </el-pagination> -->
      <el-pagination
      class="pagination"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="reqData.page"
      :page-sizes="[6, 12, 18, 24]"
      :page-size="reqData.pageSize"
      layout="total, sizes, prev, pager, next, jumper"
      :total="goodTotal"></el-pagination>
    </div>
  </div>
</template>




<style scoped lang='scss'>
.wrap {
  width: 980px;
  margin: 0 auto;
  background-color: #fefce0;
  .category-banner {
    width: 980px;
    height: 450px;
    z-index: 98;

    .banner-img {
      width: 100%;
      height: 450px;
    }
  }
  .goods {

    margin-top: 3px;
    width: 980px;
    .goods-list {
      float: left;
      width: 980px;
      background-color: #fefef5;

      .goods-li {
        float: left;
        width: 150px;
        height: 250px;
        padding-left: 13px;
        .goods-img {
          height: 150px;
          width: 150px;
        }
        &:hover {
          transform: translate3d(0, -3px, 0);
          box-shadow: 0 3px 8px rgb(0 0 0 / 20%);
        }
        p {
          font-size: 16px;
          padding-top: 8px;
          text-align: center;
          text-overflow: ellipsis;
          overflow: hidden;
          white-space: nowrap;
          color: #000;
        }

        .price {
          color: $priceColor;
        }
        .origin-price {
          font-size: 13px;
          color: #c8c8c8;
          text-decoration: line-through;
        }
      }
    }
  }
  .page{
    // position: absolute;
    background-color: #ffffff;
    width: 980px;
    top: 1453px;
    .pagination{
      padding: 0 240px;
    }
  }
}
</style>

分页功能的实现

先引入ElementPlus的分页组件
<el-pagination
      class="pagination"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="reqData.page"
      :page-sizes="[6, 12, 18, 24]"
      :page-size="reqData.pageSize"
      layout="total, sizes, prev, pager, next, jumper"
      :total="goodTotal">
</el-pagination>
size-changepageSize 改变时会触发每页条数
current-changecurrentPage 改变时会触发当前页

page-sizes? ? 每页显示个数选择器的选项设置

page-size? ? ?每页显示条目个数

current-page? ? 当前页面

total? ??总条目数

获取基础数据, 调用接口
// 获取基础列表数据
const reqData = ref({
  page: 1,
  pageSize: 12,
});
// 调用接口
const getCheapList = async () => {
  const res = await getCheapAPI(reqData.value);
  console.log(res);
  cheapList.value = res.data.list;
  goodTotal.value = res.data.total;
  reqData.value.pageSize =res.data.pageSize
};
?完善方法
// 实现分页切换页面
const handleCurrentChange = (page) => {
  reqData.value.page = page;
  getCheapList();
}
// 实现选择页面展示商品数量
const handleSizeChange = (pageSize) => {
  reqData.value.pageSize = pageSize;
  getCheapList();
}

二、二级页面商品分类组件

拆分组件结构

创建组件

配置路由

import { createRouter, createWebHashHistory } from 'vue-router'
import Layout from '@/views/Layout/index.vue'
import Login from '@/views/Login/index.vue'
import Home from '@/views/Home/index.vue'
import SubCategory from '@/views/SubCategory/index.vue'

const routes = [
  {
    // Home 页面是首页下的二级页面,所以要配置在首页路径下
    path: '/',
    component: Layout,
    children: [
      {
        // Home 页默认在首页显示,所以 path 为空
        path: '',
        component: Home,
      },
      {
        path: '/category/cheap',
        component: () => import('@/views/Category/Cheap.vue')
      },
      {
        path: '/category/hot',
        component: () => import('@/views/Category/Hot.vue')
      },
      {
        path: '/category/new',
        component: () => import('@/views/Category/New.vue')
      },
      {
        path: 'category/sub/:id',
        component: SubCategory
      }
    ]
  },
  {
    path: '/login',
    component: Login
  }
]
const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router

修改之前 HomeCategory.vue 文件

<template>
  <div class="home-category">
    <ul class="menu">
      <li v-for="item in categoryStore.categoryList" :key="item.id">
        <i :class=item.icon></i>                              
        <router-link :to="`/category/sub/${item.id}`">{{ item.categoryName }}</router-link>
        <span class="more">
          <a href="/">></a>
        </span>
      </li>
    </ul>
  </div>
</template>

封装接口

创建文件 api/category/index.js

/**
 * @description: 获取二级分类列表数据
 */
import http from '@/utils/http'

export function getCategoryFilterAPI (id) {
  return http({
    url: '/home/category/sub/filter',
      method: 'get',
      params: {
          id
      }
  })
}

创建文件 api/goods/temporary.js

?

import http from '@/utils/http'

export function getSubCategoryAPI (data) {
  return http({
    url: '/goods/temporary',
    method: 'post',
    data
  })
}

编写代码

<script setup>
import { getCategoryFilterAPI } from "@/api/category/index";
import { ref, onMounted } from "vue";
import { useRoute } from "vue-router";
import { getSubCategoryAPI } from "@/api/goods/temporary";

const route = useRoute();

const categoryData = ref({});
const getCategoryData = async () => {
  const res = await getCategoryFilterAPI(route.params.id);
  categoryData.value = res.data;
};

// 获取基础列表数据
const goodList = ref([]);
const goodTotal = ref([]);

const reqData = ref({
  categoryId: route.params.id,
  page: 1,
  pageSize: 12,
  sortField: 1,
});
const getGoodList = async () => {
  const res = await getSubCategoryAPI(reqData.value);
  goodList.value = res.data.list;
  goodTotal.value = res.data.total;
  reqData.value.pageSize =res.data.pageSize
};
const handleCurrentChange = (page) => {
  reqData.value.page = page;
  getGoodList();
}
const handleSizeChange = (pageSize) => {
  reqData.value.pageSize = pageSize;
  getGoodList();
}
// tab切换回调
const tabChange = () => {
  console.log("tab切换了", reqData.value.sortField);
  reqData.value.page = 1;
  getGoodList();
};

onMounted(() => {
  getCategoryData(), getGoodList();
});
console.log(goodList);
</script>

<template>
  <div class="container">
    <!-- 面包屑 -->
    <div class="bread-container">
      <el-breadcrumb separator=">">
        <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
        <el-breadcrumb-item :to="{ path: `/category/sub/${categoryData.id}` }">{{
          categoryData.categoryName
        }}</el-breadcrumb-item>
      </el-breadcrumb>
    </div>
    <div class="body">
      <el-tabs v-model="reqData.sortField" @tab-change="tabChange">
        <el-tab-pane label="精选热门" name="1"></el-tab-pane>
        <el-tab-pane label="低价商品" name="2" ></el-tab-pane>
        <el-tab-pane label="最新上架" name="3"></el-tab-pane>
      </el-tabs>
    </div>
    <!-- 商品列表-->
    <div class="goods">
      <ul class="goods-list">
        <li class="goods-li" v-for="item in goodList" :key="item.id">
          <RouterLink to="/">
            <img
              class="goods-img"
              :src="require(`@/assets/img/${item.picture1}.jpg`)"
              :alt="item.alt"
            />
            <p class="name">{{ item.goodsName }}</p>
            <p class="origin-price">&yen;{{ item.originalPrice }}</p>
            <p class="price">&yen;{{ item.price }}</p>
          </RouterLink>
        </li>
      </ul>
    </div>
    <div class="page">
      <!-- <el-pagination  class="pagination" background layout="prev, pager, next"
       :total="100" :page-size="reqData.pageSize" >
      </el-pagination> -->
      <el-pagination
      class="pagination"

      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="reqData.page"
      :page-sizes="[6, 12, 18, 24]"
      :page-size="reqData.pageSize"
      layout="total, sizes, prev, pager, next, jumper"
      :total="goodTotal">
    </el-pagination>
    </div>
  </div>
</template>




<style lang="scss" scoped>
.bread-container {
  padding: 15px 0;
  color: #666;
}

.container {
  padding: 20px 10px;
  background-color: #fff;
  width: 980px;
  margin: auto;
  .body {
    display: flex;
    flex-wrap: wrap;
    padding: 0 10px;
  }
  .goods {
    display: flex;
    // position: absolute;
    width: 980px;
    background-color: #fefef5;
    .goods-list {
      float: left;
      width: 980px;
      .goods-li {
        float: left;
        width: 150px;
        height: 250px;
        padding-left: 13px;
        .goods-img {
          height: 150px;
          width: 150px;
        }
        &:hover {
          transform: translate3d(0, -3px, 0);
          box-shadow: 0 3px 8px rgb(0 0 0 / 20%);
        }
        p {
          font-size: 16px;
          padding-top: 8px;
          text-align: center;
          text-overflow: ellipsis;
          overflow: hidden;
          white-space: nowrap;
          color: #000;
        }

        .price {
          color: $priceColor;
        }
        .origin-price {
          font-size: 13px;
          color: #c8c8c8;
          text-decoration: line-through;
        }
      }
    }
  }

  .page{
    position: absolute;
    background-color: #fff;
    width: 980px;
    .pagination{
      padding: 0 240px;
    }
  }
}
</style>

面包屑导航功能的实现

引入ElementPlus的面包屑组件
<el-breadcrumb separator=">">
        <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
        <el-breadcrumb-item :to="{ path: `/category/sub/${categoryData.id}` }">{{
          categoryData.categoryName
        }}</el-breadcrumb-item>
</el-breadcrumb>
调用接口
const route = useRoute();

const categoryData = ref({});
const getCategoryData = async () => {
  const res = await getCategoryFilterAPI(route.params.id);
  categoryData.value = res.data;
};

基础分类部分

引入组件
<el-tabs v-model="reqData.sortField" @tab-change="tabChange">
        <el-tab-pane label="精选热门" name="1"></el-tab-pane>
        <el-tab-pane label="低价商品" name="2" ></el-tab-pane>
        <el-tab-pane label="最新上架" name="3"></el-tab-pane>
</el-tabs>

el-tab-pane的? name绑定的是reqData.sortField, sortField要在数据库有代表意思相同(名称不需要一样)的属性

获取基础数据, 调用接口
const goodList = ref([]);
const goodTotal = ref([]);

const reqData = ref({
  categoryId: route.params.id,
  page: 1,
  pageSize: 12,
  sortField: 1,
});
const getGoodList = async () => {
  const res = await getSubCategoryAPI(reqData.value);
  goodList.value = res.data.list;
  goodTotal.value = res.data.total;
  reqData.value.pageSize =res.data.pageSize
};
切换基础分类
// tab切换回调
const tabChange = () => {
  console.log("tab切换了", reqData.value.sortField);
  reqData.value.page = 1;
  getGoodList();
};

文章来源:https://blog.csdn.net/guaiwu_/article/details/135707721
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。