主页原型图
主页文件夹
编程思路
一、分析结构
1、新建主文件夹 里面创建入口文件 组件文件 分模块
2、新建模块文件 在入口文件引入组件
<script setup>
import HomeBanner from './components/HomeBanner.vue';
import HomeCategory from './components/HomeCategory.vue';
import HomeProduct from './components/HomeProduct.vue';
import HomeNew from './components/HomeNew.vue';
import HomeHot from './components/HomeHot.vue';
</script>
<template>
<div class="container">
<HomeCategory />
<HomeBanner />
</div>
<HomeNew />
<HomeHot />
<HomeProduct />
</template>
<style></style>
二、准备模板
三、编写组件
一个banner组件 一个商品推荐页组件
banner:
<script setup>
import { getBannerAPI } from '@/apis/home.js'
import { onMounted, ref } from 'vue';
const bannerList = ref([])
const getBanner = async () => {
const res = await getBannerAPI()
if (res.code !== '1') {
return
}
bannerList.value = res.result
}
onMounted(() => getBanner())
</script>
<template>
<div class="home-banner">
<el-carousel height="500px">
<el-carousel-item v-for="item in bannerList" :key="item.id">
<img :src=item.imgUrl>
</el-carousel-item>
</el-carousel>
</div>
</template>
<style scoped lang='scss'>
.home-banner {
width: 1240px;
height: 500px;
position: absolute;
left: 0;
top: 0;
z-index: 98;
img {
width: 100%;
height: 500px;
}
}
</style>
商品推荐页:
<script setup>
defineProps({
title: {
type: String,
default: ''
},
subTitle: {
type: String,
default: ''
}
})
</script>
<template>
<div class="home-panel">
<div class="container">
<div class="head">
<!-- 主标题和副标题 -->
<h3>
{{title}}<small>{{subTitle}}</small>
</h3>
</div>
<!-- 主体内容区域 -->
<slot></slot>
</div>
</div>
</template>
<style scoped lang='scss'>
.home-panel {
background-color: #fff;
.head {
padding: 40px 0;
display: flex;
align-items: flex-end;
h3 {
flex: 1;
font-size: 32px;
font-weight: normal;
margin-left: 6px;
height: 35px;
line-height: 35px;
small {
font-size: 16px;
color: #999;
margin-left: 20px;
}
}
}
}
</style>
商品推荐页的插槽:
<script setup>
import { onMounted, ref } from 'vue';
import HomePanel from './HomePanel.vue';
import { findNewAPI } from '@/apis/home'
const newList = ref([])
async function getNewList() {
const res = await findNewAPI();
if (res.code !== '1') {
return
}
newList.value = res.result
}
onMounted(() => {
getNewList()
})
</script>
<template>
<HomePanel title="新鲜好物" sub-title="新鲜出炉 品质靠谱">
<ul class="goods-list">
<li v-for="item in newList" :key="item.id">
<RouterLink :to="`/detail/${item.id}`">
<img :src="item.picture" alt="" />
<p class="name">{{ item.name }}</p>
<p class="price">¥{{ item.price }}</p>
</RouterLink>
</li>
</ul>
</HomePanel>
</template>
<style scoped lang='scss'>
.goods-list {
display: flex;
justify-content: space-between;
height: 406px;
li {
width: 306px;
height: 406px;
background: #f0f9f4;
transition: all .5s;
&:hover {
transform: translate3d(0, -3px, 0);
box-shadow: 0 3px 8px rgb(0 0 0 / 20%);
}
img {
width: 306px;
height: 306px;
}
p {
font-size: 22px;
padding-top: 12px;
text-align: center;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.price {
color: $priceColor;
}
}
}
</style>
四、接口调用
编写拦截器(一般使用模板):
// axios基础封装
import axios from 'axios'
import { useUserStore } from '@/stores/userStore.js'
import { ElMessage } from 'element-plus'
import 'element-plus/theme-chalk/el-message.css'
import router from '@/router'
// 创建axios实例
const httpInstance = axios.create({
baseURL: 'http://pcapi-xiaotuxian-front-devtest.itheima.net',
timeout: 5000,
})
// axios请求拦截器
httpInstance.interceptors.request.use(config => {
// 1. 从pinia获取token数据
const userStore = useUserStore()
// 2. 按照后端的要求拼接token数据
const token = userStore.userInfo.token
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
}, e => Promise.reject(e))
// axios响应式拦截器
httpInstance.interceptors.response.use(res => res.data, e => {
// 处理响应失败 统一错误提示
ElMessage({ type: 'warning', message: e.response.data.message || '系统错误' })
// 401 token 错误处理
if (e.response.status === 401) {
const userStore = useUserStore()
userStore.clearUserInfo()
router.push('/login')
}
return Promise.reject(e)
})
export default httpInstance
接口编写模板:
import http from "@/utils/http";
export function getXXX( ) {
return http({
url: '/home/home',
})
}
1、轮播图数据接口
2、获取新鲜好物接口
import httpInstance from "@/utils/http";
// 获取 轮播图 数据
export function getBannerAPI(params = {}) {
// 默认为1 商品为2
const { distributionSite = '1' } = params
return httpInstance({
url: '/home/banner',
params: {
distributionSite
}
})
}
/**
* @description: 获取新鲜好物
* @param {*}
* @return {*}
*/
export const findNewAPI = () => {
return httpInstance({
url: '/home/new'
})
}
/**
* @description: 获取所有商品模块
* @param {*}
* @return {*}
*/
export const getGoodsAPI = () => {
return httpInstance({
url: '/home/goods'
})
}