目录
(6)把运行出的网址复制粘贴到游览器打开(最好用谷歌游览器打开)会报以下错误
(7)打开App.vue终端复制粘贴游览器报错需要我们下载的命令 ,即可运行成功
(4)数组.数组(例:categoryData.children)
一.elementPlus组件库导入
首先要确保项目中已经安装了Vue.
(1)在Vue项目中安装Element Plus
1.执行Vue脚手架命令,命令如下(通俗来说就把如下命令打在Visual Studio Code下新建的文件夹的终端中):
npm init vue@latest
2.按照下图步骤进行选择操作
进行完上图的选择操作后再依次复制以下命令,并在粘贴完每条命令后点击回车键
cd rabbit-shop
npm install
3.通过npm来安装Element Plus(注意:需在项目根目录下执行以下命令 从此处命令开始,后面的命令都均在 https://element-plus-docs.bklab.cn/zh-CN/ 网站中找到复制)
npm install element-plus --save
(2)在Vue项目中引入Element Plus
1.下载自动按需导入的插件,如下图所示
2.完善配置文件代码
(3)使用组件
1.在https://element-plus-docs.bklab.cn/zh-CN/网址上复制粘贴代码
2.在App.vue文件处右键打开终端输入,以下命令
npm run dev
3.把运行出的网址复制粘贴到游览器打开(最好用谷歌游览器打开)
结果图展示:
二.自定义主题
(1)下载scss
(2)覆盖样式
(3) 书写样式代码
(4) 更改主题色
(5) 配置样式文件
(6)把运行出的网址复制粘贴到游览器打开(最好用谷歌游览器打开)会报以下错误
(7)打开App.vue终端复制粘贴游览器报错需要我们下载的命令 ,即可运行成功
结果图展示(左新右旧):
三、Axios的配置和使用
(1)下载Axios
(2)配置axios
https://pcapi-xiaotuxian-front-devtest.itheima.net
(3)封装测试请求接口
(4)发送get请求
(5)查看请求结果打印数据
(6)在 httpjs文件中添加拦截器
http.js文件中的完整代码如下:
四、Layout页面搭建
(1)Layout模块的前期模拟结构搭建
1.在rabbit-shop\src\views路径下新建一个名为Layout的文件夹和一个名为Login的文件夹,接着,分别在两个文件夹下面新建一个名为index.vue的文件
2.分别在Layout文件夹和Login文件夹下的index.vue文件中,写入如下代码:
3.在rabbit-shop\src\router路径下的index.js文件中写入对应的路由配置,代码如图:
4.在Layout文件夹下的index.vue文件中写入router-view标签
5.在rabbit-shop\src\styles路径下的新建一个var.scss文件(在文件中分别赋予要使用的颜色各自的别名)
6.使用颜色的别名
7.在\rabbit-shop\vite.config.js文件中写入如下代码:
注意:该出代码的标点符号不要输出位置
8.最后,在App.vue文件处点击右键打开终端输入npm run dev,把运行出的网址复制粘贴到游览器中打开(推荐使用谷歌游览器)
结果图展示:
(2)字体图标引入
1.rabbit-shop\src\styles路径下创建common.css样式文件并输入如下代码(代码过长建议直接复制):
// 重置样式
* {
box-sizing: border-box;
}
html {
height: 100%;
font-size: 14px;
}
body {
height: 100%;
color: #333;
min-width: 1240px;
font: 1em/1.4 'Microsoft Yahei', 'PingFang SC', 'Avenir', 'Segoe UI',
'Hiragino Sans GB', 'STHeiti', 'Microsoft Sans Serif', 'WenQuanYi Micro Hei',
sans-serif;
}
body,
ul,
h1,
h3,
h4,
p,
dl,
dd {
padding: 0;
margin: 0;
}
a {
text-decoration: none;
color: #333;
outline: none;
}
i {
font-style: normal;
}
input[type='text'],
input[type='search'],
input[type='password'],
input[type='checkbox'] {
padding: 0;
outline: none;
border: none;
-webkit-appearance: none;
&::placeholder {
color: #ccc;
}
}
img {
max-width: 100%;
max-height: 100%;
vertical-align: middle;
background: #ebebeb url('@/assets/images/200.png') no-repeat center / contain;
}
ul {
list-style: none;
}
#app {
background: #f5f5f5;
user-select: none;
}
.container {
width: 1240px;
margin: 0 auto;
position: relative;
}
.ellipsis {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.ellipsis-2 {
word-break: break-all;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.fl {
float: left;
}
.fr {
float: right;
}
.clearfix:after {
content: '.';
display: block;
visibility: hidden;
height: 0;
line-height: 0;
clear: both;
}
// reset element
.el-breadcrumb__inner.is-link {
font-weight: 400 !important;
}
2.在rabbit-shop\src\路径下的main.js的文件中导入common.scss文件
4.在LaoyoutHeader.vue组件文件中输入如下代码(代码过长建议直接复制):
<script setup>
</script>
<template>
<header class='app-header'>
<div class="container">
<h1 class="logo">
<RouterLink to="/">小兔鲜</RouterLink>
</h1>
<ul class="app-header-nav">
<li class="home">
<RouterLink to="/">首页</RouterLink>
</li>
<li> <RouterLink to="/">居家</RouterLink> </li>
<li> <RouterLink to="/">美食</RouterLink> </li>
<li> <RouterLink to="/">服饰</RouterLink> </li>
</ul>
<div class="search">
<i class="iconfont icon-search"></i>
<input type="text" placeholder="搜一搜">
</div>
<!-- 头部购物车 -->
</div>
</header>
</template>
<style scoped lang='scss'>
.app-header {
background: #fff;
.container {
display: flex;
align-items: center;
}
.logo {
width: 200px;
a {
display: block;
height: 132px;
width: 100%;
text-indent: -9999px;
background: url('@/assets/images/logo.png') no-repeat center 18px / contain;
}
}
.app-header-nav {
width: 820px;
display: flex;
padding-left: 40px;
position: relative;
z-index: 998;
li {
margin-right: 40px;
width: 38px;
text-align: center;
a {
font-size: 16px;
line-height: 32px;
height: 32px;
display: inline-block;
&:hover {
color: $xtxColor;
border-bottom: 1px solid $xtxColor;
}
}
.active {
color: $xtxColor;
border-bottom: 1px solid $xtxColor;
}
}
}
.search {
width: 170px;
height: 32px;
position: relative;
border-bottom: 1px solid #e7e7e7;
line-height: 32px;
.icon-search {
font-size: 18px;
margin-left: 5px;
}
input {
width: 140px;
padding-left: 5px;
color: #666;
}
}
.cart {
width: 50px;
.curr {
height: 32px;
line-height: 32px;
text-align: center;
position: relative;
display: block;
.icon-cart {
font-size: 22px;
}
em {
font-style: normal;
position: absolute;
right: 0;
top: 0;
padding: 1px 6px;
line-height: 1;
background: $helpColor;
color: #fff;
font-size: 12px;
border-radius: 10px;
font-family: Arial;
}
}
}
}
</style>
<template>
<footer class="app_footer">
<!-- 联系我们 -->
<div class="contact">
<div class="container">
<dl>
<dt>客户服务</dt>
<dd><i class="iconfont icon-kefu"></i> 在线客服</dd>
<dd><i class="iconfont icon-question"></i> 问题反馈</dd>
</dl>
<dl>
<dt>关注我们</dt>
<dd><i class="iconfont icon-weixin"></i> 公众号</dd>
<dd><i class="iconfont icon-weibo"></i> 微博</dd>
</dl>
<dl>
<dt>下载APP</dt>
<dd class="qrcode"><img src="@/assets/images/qrcode.jpg" /></dd>
<dd class="download">
<span>扫描二维码</span>
<span>立马下载APP</span>
<a href="javascript:;">下载页面</a>
</dd>
</dl>
<dl>
<dt>服务热线</dt>
<dd class="hotline">400-0000-000 <small>周一至周日 8:00-18:00</small></dd>
</dl>
</div>
</div>
<!-- 其它 -->
<div class="extra">
<div class="container">
<div class="slogan">
<a href="javascript:;">
<i class="iconfont icon-footer01"></i>
<span>价格亲民</span>
</a>
<a href="javascript:;">
<i class="iconfont icon-footer02"></i>
<span>物流快捷</span>
</a>
<a href="javascript:;">
<i class="iconfont icon-footer03"></i>
<span>品质新鲜</span>
</a>
</div>
<!-- 版权信息 -->
<div class="copyright">
<p>
<a href="javascript:;">关于我们</a>
<a href="javascript:;">帮助中心</a>
<a href="javascript:;">售后服务</a>
<a href="javascript:;">配送与验收</a>
<a href="javascript:;">商务合作</a>
<a href="javascript:;">搜索推荐</a>
<a href="javascript:;">友情链接</a>
</p>
<p>CopyRight © 小兔鲜儿</p>
</div>
</div>
</div>
</footer>
</template>
<style scoped lang='scss'>
.app_footer {
overflow: hidden;
background-color: #f5f5f5;
padding-top: 20px;
.contact {
background: #fff;
.container {
padding: 60px 0 40px 25px;
display: flex;
}
dl {
height: 190px;
text-align: center;
padding: 0 72px;
border-right: 1px solid #f2f2f2;
color: #999;
&:first-child {
padding-left: 0;
}
&:last-child {
border-right: none;
padding-right: 0;
}
}
dt {
line-height: 1;
font-size: 18px;
}
dd {
margin: 36px 12px 0 0;
float: left;
width: 92px;
height: 92px;
padding-top: 10px;
border: 1px solid #ededed;
.iconfont {
font-size: 36px;
display: block;
color: #666;
}
&:hover {
.iconfont {
color: $xtxColor;
}
}
&:last-child {
margin-right: 0;
}
}
.qrcode {
width: 92px;
height: 92px;
padding: 7px;
border: 1px solid #ededed;
}
.download {
padding-top: 5px;
font-size: 14px;
width: auto;
height: auto;
border: none;
span {
display: block;
}
a {
display: block;
line-height: 1;
padding: 10px 25px;
margin-top: 5px;
color: #fff;
border-radius: 2px;
background-color: $xtxColor;
}
}
.hotline {
padding-top: 20px;
font-size: 22px;
color: #666;
width: auto;
height: auto;
border: none;
small {
display: block;
font-size: 15px;
color: #999;
}
}
}
.extra {
background-color: #333;
}
.slogan {
height: 178px;
line-height: 58px;
padding: 60px 100px;
border-bottom: 1px solid #434343;
display: flex;
justify-content: space-between;
a {
height: 58px;
line-height: 58px;
color: #fff;
font-size: 28px;
i {
font-size: 50px;
vertical-align: middle;
margin-right: 10px;
font-weight: 100;
}
span {
vertical-align: middle;
text-shadow: 0 0 1px #333;
}
}
}
.copyright {
height: 170px;
padding-top: 40px;
text-align: center;
color: #999;
font-size: 15px;
p {
line-height: 1;
margin-bottom: 20px;
}
a {
color: #999;
line-height: 1;
padding: 0 10px;
border-right: 1px solid #999;
&:last-child {
border-right: none;
}
}
}
}
</style>
<script setup>
</script>
<template>
<nav class="app-topnav">
<div class="container">
<ul>
<template v-if="true">
<li><a href="javascript:;"><i class=" iconfont icon-user"></i>周杰伦</a></li>
<li>
<el-popconfirm title="确认退出吗?" confirm-button-text="确认" cancel-button-text="取消">
<template #reference>
<a href="javascript:;">退出登录</a>
</template>
</el-popconfirm>
</li>
<li><a href="javascript:;">我的订单</a></li>
<li><a href="javascript:;">会员中心</a></li>
</template>
<template v-else>
<li><a href="javascript:;">请先登录</a></li>
<li><a href="javascript:;">帮助中心</a></li>
<li><a href="javascript:;">关于我们</a></li>
</template>
</ul>
</div>
</nav>
</template>
<style scoped lang="scss">
.app-topnav {
background: #333;
ul {
display: flex;
height: 53px;
justify-content: flex-end;
align-items: center;
li {
a {
padding: 0 15px;
color: #cdcdcd;
line-height: 1;
display: inline-block;
i {
font-size: 14px;
margin-right: 2px;
}
&:hover {
color: $xtxColor;
}
}
~li {
a {
border-left: 2px solid #666;
}
}
}
}
}
</style>
7.在rabbit-shop\src\views\Layout路径下的index.vue文件中(导入 、注册、使用)这些组件:
8.运用阿里巴巴矢量图标库中找到需要的矢量图标添加在rabbit-shop文件夹下的index.html文件中:
阿里巴巴矢量图标库的官方链接:
https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=4770317
第一张图中在href=""中引入的矢量图标的代码:
//at.alicdn.com/t/font_2143783_iq6z4ey5vu.css
(3)前后端数据交互
1.在rabbit-shop\src\apis路径下的layout.js文件中创建接口函数 输入下图代码:
2. 在LayoutHeader.vue组件文件中导入步骤1中的接口函数并进行封装(1图中导入代码有所欠缺,请读者结合2图一并观看):
1图:
2图:
(4)渲染数据
1.在LayoutHeader.vue组件文件中把我们需要的数据渲染出来:
结果图展示:
(5)吸顶导航
1.在rabbit-shop\src\views\Layout\components路径下新建一个名为LayoutFixed组件文件并在其中输入如下代码:
<script setup>
</script>
<template>
<div class="app-header-sticky">
<div class="container">
<RouterLink class="logo" to="/" />
<!-- 导航区域 -->
<ul class="app-header-nav ">
<li class="home">
<RouterLink to="/">首页</RouterLink>
</li>
<li>
<RouterLink to="/">居家</RouterLink>
</li>
<li>
<RouterLink to="/">美食</RouterLink>
</li>
<li>
<RouterLink to="/">服饰</RouterLink>
</li>
<li>
<RouterLink to="/">母婴</RouterLink>
</li>
<li>
<RouterLink to="/">个护</RouterLink>
</li>
<li>
<RouterLink to="/">严选</RouterLink>
</li>
<li>
<RouterLink to="/">数码</RouterLink>
</li>
<li>
<RouterLink to="/">运动</RouterLink>
</li>
<li>
<RouterLink to="/">杂项</RouterLink>
</li>
</ul>
<div class="right">
<RouterLink to="/">品牌</RouterLink>
<RouterLink to="/">专题</RouterLink>
</div>
</div>
</div>
</template>
<style scoped lang='scss'>
.app-header-sticky {
width: 100%;
height: 80px;
position: fixed;
left: 0;
top: 0;
z-index: 999;
background-color: #fff;
border-bottom: 1px solid #e4e4e4;
// 此处为关键样式!!!
// 状态一:往上平移自身高度 + 完全透明
transform: translateY(-100%);
opacity: 0;
// 状态二:移除平移 + 完全不透明
&.show {
transition: all 0.3s linear;
transform: none;
opacity: 1;
}
.container {
display: flex;
align-items: center;
}
.logo {
width: 200px;
height: 80px;
background: url("@/assets/images/logo.png") no-repeat right 2px;
background-size: 160px auto;
}
.right {
width: 220px;
display: flex;
text-align: center;
padding-left: 40px;
border-left: 2px solid $xtxColor;
a {
width: 38px;
margin-right: 40px;
font-size: 16px;
line-height: 1;
&:hover {
color: $xtxColor;
}
}
}
}
.app-header-nav {
width: 820px;
display: flex;
padding-left: 40px;
position: relative;
z-index: 998;
li {
margin-right: 40px;
width: 38px;
text-align: center;
a {
font-size: 16px;
line-height: 32px;
height: 32px;
display: inline-block;
&:hover {
color: $xtxColor;
border-bottom: 1px solid $xtxColor;
}
}
.active {
color: $xtxColor;
border-bottom: 1px solid $xtxColor;
}
}
}
</style>
2.在index.vue组件文件中引入、注册、使用该组件
3.在LayoutFixed.vue组件文件中增加class类名
4.通过判定页面滑动距离 决定fix组件什么时候出现(就要去获取页面的滚动距离)步骤如下:
结果图展示:
(6)Pinia仓库的建立和使用
1.在rabbit-shop\src\stores路径下新建一个名为category.js文件并输入如下代码:
2.在index.vue文件中引入pinia
3.在LayoutHeader.vue组件文件中引入pinia仓库
4.在index.vue组件文件中的script标签加入setup并把其下的export default方法删除,如下图所示:
(7)onMounted钩子函数
1.在rabbit-shop\src\views\Layout路径下的index.vue组件文件中导入和使用onMounted钩子函数:
Layout页面的总结构设计图:
index.vue组件文件的总代码图 :
(在rabbit-shop\src\views\Layout路径下的)
LayoutHeader.vue组件文件的总代码图:
(在rabbit-shop\src\views\Layout\components 路径下的)
LayoutFixed.vue组件文件的总代码图:
(在rabbit-shop\src\views\Layout路径下的)
LayoutFooter.vue组件文件的总代码图:
(在rabbit-shop\src\views\Layout路径下的)
LayoutNav.vue组件文件的总代码图:
(在rabbit-shop\src\views\Layout路径下的)
结果图展示:
五、Home页面搭建
左边商品栏:
(1)新建页面,搭建内容
在rabbit-shop\src\views路径下新建一个名为Home的文件夹,后在该文件夹下面分别新建一个名为components的文件夹和一个名为index.vue的组件文件,接着,在components文件夹下新建一个名为HomeCategory.vue的组件文件,如下图所示:
在HomeCategory.vue的组件文件中复制粘贴以下代码:
<script setup>
</script>
<template>
<div class="home-category">
<ul class="menu">
<li v-for="item in 9" :key="item">
<RouterLink to="/">居家</RouterLink>
<RouterLink v-for="i in 2" :key="i" to="/">南北干货</RouterLink>
<!-- 弹层layer位置 -->
<div class="layer">
<h4>分类推荐 <small>根据您的购买或浏览记录推荐</small></h4>
<ul>
<li v-for="i in 5" :key="i">
<RouterLink to="/">
<img alt="" />
<div class="info">
<p class="name ellipsis-2">
男士外套
</p>
<p class="desc ellipsis">男士外套,冬季必选</p>
<p class="price"><i>¥</i>200.00</p>
</div>
</RouterLink>
</li>
</ul>
</div>
</li>
</ul>
</div>
</template>
<style scoped lang='scss'>
.home-category {
width: 250px;
height: 500px;
background: rgba(0, 0, 0, 0.8);
position: relative;
z-index: 99;
.menu {
li {
padding-left: 40px;
height: 55px;
line-height: 55px;
&:hover {
background: $xtxColor;
}
a {
margin-right: 4px;
color: #fff;
&:first-child {
font-size: 16px;
}
}
.layer {
width: 990px;
height: 500px;
background: rgba(255, 255, 255, 0.8);
position: absolute;
left: 250px;
top: 0;
display: none;
padding: 0 15px;
h4 {
font-size: 20px;
font-weight: normal;
line-height: 80px;
small {
font-size: 16px;
color: #666;
}
}
ul {
display: flex;
flex-wrap: wrap;
li {
width: 310px;
height: 120px;
margin-right: 15px;
margin-bottom: 15px;
border: 1px solid #eee;
border-radius: 4px;
background: #fff;
&:nth-child(3n) {
margin-right: 0;
}
a {
display: flex;
width: 100%;
height: 100%;
align-items: center;
padding: 10px;
&:hover {
background: #e3f9f4;
}
img {
width: 95px;
height: 95px;
}
.info {
padding-left: 10px;
line-height: 24px;
overflow: hidden;
.name {
font-size: 16px;
color: #666;
}
.desc {
color: #999;
}
.price {
font-size: 22px;
color: $priceColor;
i {
font-size: 16px;
}
}
}
}
}
}
}
// 关键样式 hover状态下的layer盒子变成block
&:hover {
.layer {
display: block;
}
}
}
}
}
</style>
(2) 引入组件
在rabbit-shop\src\views\Home路径下的index.vue文件中引入HomeCategory组件:
(3)定义路由
在 rabbit-shop\src\router路径下的index.js定义对应的路由:
(4)路由出口
在rabbit-shop\src\views\Layout路径下的index.vue文件中使用<router-view></router-view>组件:
(5) 引入pinia仓库
在HomeCategory文件中引入pinia仓库:
(6) 渲染左边商品栏的数据
在HomeCategory文件中写入如下v-for语句:
结果图展示:
再根据浏览器中呈现的页面点击右键检查在点击console选项页面查看对应数组的名字根据数组名在HomeCategory文件中写入如下代码:
1.slice(截取 )
<RouterLink v-for="i in item.children.slice(0,2)" :key="i" to="/">{{i.name}}</RouterLink>
<!-- slice(0,2)是0到2的意思,也就是只取0,1的数组数据 -->
结果图展示:
接着,根据浏览器显示的数组名(用上面使用过的方法查看)在HomeCategory文件中写入如下代码:
轮播图:
(1)静态页面
在rabbit-shop\src\views\Home\components路径下新建一个名为HomeBanner.vue组件文件,并在其中复制粘贴以下代码,如下图所示:
<script setup>
</script>
<template>
<div class="home-banner">
<el-carousel height="500px">
<el-carousel-item v-for="item in 4" :key="item">
<img src="http://yjy-xiaotuxian-dev.oss-cn-beijing.aliyuncs.com/picture/2021-04-15/6d202d8e-bb47-4f92-9523-f32ab65754f4.jpg" alt="">
</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>
然后,在Home文件夹下的index.vue组件文件中导入Homebanner组件:
效果图展示:
(2)封装请求函数
在rabbit-shop\src\apis路径下新建一个名为home.js的文件并在其中输入如下代码封装请求函数:
(3)发送请求,拿到数据
在<script setup></script>标签中输入后续代码:
从apis/home.js中导入封装好的getBannerAPI函数:
导入onmounted函数,并在onmounted函数中调用getBannerAPI函数:
拿到res,打印res,检查是否成功拿到数据:
定义一个数组BannerList,把res中拿到的结果赋值给BannerList:
(4)渲染数据轮播图数据
根据浏览器右键检查页面显示的数组名(查看方式前面有讲),在HomeBanner.vue文件下进行渲染操作,代码图如下 :
商品面板:
(1)知识点-props (使用方法)
使用方法:看以下例子可知
在某某文件夹下的src\components路径下新建一个名为PropsCom.vue组件文件并在该文件下输入以下代码:
在该某文件夹下的app.vue文件中引入PropsCom组件:
效果图展示:
(2)完成面板组件
在rabbit-shop\src\views\Home\components路径下新建一个名为HomePanel.vue的组件文件并在该文件中复制粘贴以下代码:
<template>
<div class="home-panel">
<div class="container">
<div class="head">
<!-- 主标题和副标题 -->
<h3>
新鲜好物<small>新鲜出炉 品质靠谱</small>
</h3>
</div>
<!-- 主体内容区域 -->
<div> 主体内容 </div>
</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>
然后,在Home文件夹下的index.vue组件文件中引入该组件:
效果图展示:
接着,在HomePanel.vue文件中的主标题和副标题处进行修改:
在Home文件夹下的index.vue文件中导入并使用<home-panel>组件:
效果图展示:
1. <slot>标签的用途
在HomePanel.vue文件中的<slot>标签的用途:
可以把在<home-panel>组件之间的信息解析到slot标签所在的位置
例如:
分别在Home文件夹下的index.vue文件中的两个<home-panel>标签之间输入1111和2222,接着在HomePanel文件中写入<slot>标签,浏览器页面中就会在<slot>标签位置处显示1111和2222:
后在rabbit-shop\src\views\Home\components路径下新建一个名为HomeNew.vue的组件文件和一个名为HomeHot.vue的组件文件,并分别在两个组件文件中导入并使用<home-panel>组件:
在Home文件夹下的index.vue文件中导入并使用<home-new>和<home-hot>标签:
新鲜好物商品面板:
在HomeNew.vue文件中使用使用插值语法:
再在 HomeNew.vue文件中文件中复制粘贴以下的样式代码:
<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>
接着,在home.js文件中封装获取新鲜好物的函数:
后从apis/home.js中导入封装好的getNewAPI函数,导入onmounted函数,并在onmounted函数中调用getNewAPI函数,拿到res,打印res,检查是否成功拿到数据,定义一个数组NewList,把res中拿到的结果赋值给BannerList:
HomeNew.vue文件总代码:
效果图展示:
人气推荐商品面板:
制作步骤与新鲜好物商品面板制作步骤基本相同
HomeHot.vue文件总代码:
效果图展示:
各个商品馆面板:
在rabbit-shop\src\views\Home\components路径下新建一个名为HomeProduct.vue组件文件:
再在Home文件夹下的index.vue文件中导入和使用<home-product>组件:
后在apis/home.js中封装一个名为getGoodsAPI函数:
然后,在浏览器中右键检查中显示下图的“操作成功”提示就代表封装成功:
接着, 从apis/home.js中导入封装好的getGoodsAPI函数,导入onmounted函数,并在onmounted函数中调用getGoodsAPI函数,拿到res,打印res,检查是否成功拿到数据,定义一个数组goodsProduct,把res中拿到的结果赋值给goodsProduct:
在HomeProduct文件中导入<HomePanel>组件:
在HomeProduct文件中的<template>标签中复制粘贴以下代码:
<div class="box">
<RouterLink class="cover" to="/">
<img />
<strong class="label">
<span>馆</span>
<span></span>
</strong>
</RouterLink>
<ul class="goods-list">
<li >
<RouterLink to="/" class="goods-item">
<img alt="" />
<p class="name ellipsis"></p>
<p class="desc ellipsis"></p>
<p class="price">¥</p>
</RouterLink>
</li>
</ul>
</div>
接着在HomeProduct文件中的<template>标签中的以上代码作插值语法处理(对照这浏览器右键检查中的数组名进行操作):
最后,在rabbit-shop\src\views\Home\components路径下新建一个名为GoodsItem.vue的组件文件并把HomeProduct文件中的下图红框部分的代码剪切粘贴到GoodsItem.vue组件文件中,并在该文件中使用Props方法和加入如下样式代码:
剪切粘贴到:
使用Props方法位置:
样式代码:
<style scoped lang='scss'>
.goods-item {
display: block;
width: 220px;
padding: 20px 30px;
text-align: center;
transition: all 0.5s;
&:hover {
transform: translate3d(0, -3px, 0);
box-shadow: 0 3px 8px rgb(0 0 0 / 20%);
}
img {
width: 160px;
height: 160px;
}
p {
padding-top: 10px;
}
.name {
font-size: 16px;
}
.desc {
color: #999;
height: 29px;
}
.price {
color: $priceColor;
font-size: 20px;
}
}
</style>
GoodsItem.vue的文件的总代码:
HomeProduct.vue文件的总代码:
六、Category页面搭建
在rabbit-shop\src\views路径下新建一个名为Category的文件夹并在该文件夹下新建一个index.vue的组件文件,接着,在文件中输入如下代码:
在rabbit-shop\src\router路径下的index.js文件中定义category路由:
效果图展示:
在rabbit-shop\src\router路径下的index.js文件中截图红框处添加/:id字段:
分别在rabbit-shop\src\views\Layout\components路径下的LayoutHeader.vue和LayoutFixed.vue组件文件中使用模版字符串的方法和``(反引号)的方法:
在rabbit-shop\src\views\Category路径下的index.vue文件中复制粘贴以下代码:
<script setup>
</script>
<template>
<div class="top-category">
<div class="container m-top-20">
<!-- 面包屑 -->
<div class="bread-container">
<el-breadcrumb separator=">">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>居家</el-breadcrumb-item>
</el-breadcrumb>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
.top-category {
h3 {
font-size: 28px;
color: #666;
font-weight: normal;
text-align: center;
line-height: 100px;
}
.sub-list {
margin-top: 20px;
background-color: #fff;
ul {
display: flex;
padding: 0 32px;
flex-wrap: wrap;
li {
width: 168px;
height: 160px;
a {
text-align: center;
display: block;
font-size: 16px;
img {
width: 100px;
height: 100px;
}
p {
line-height: 40px;
}
&:hover {
color: $xtxColor;
}
}
}
}
}
.ref-goods {
background-color: #fff;
margin-top: 20px;
position: relative;
.head {
.xtx-more {
position: absolute;
top: 20px;
right: 20px;
}
.tag {
text-align: center;
color: #999;
font-size: 20px;
position: relative;
top: -20px;
}
}
.body {
display: flex;
justify-content: space-around;
padding: 0 40px 30px;
}
}
.bread-container {
padding: 25px 0;
}
}
</style>
效果图展示:
在rabbit-shop\src\apis路径下新建一个名为category.js的文件:
(1)params对象
含义:params是一个对象,它包含在当前路由路径中匹配的所有动态片段的值。
例:当你使用 Vue Router 定义一个路由时,可以在路径中包含动态片段,这些片段被称为路由参数。
// 定义一个路由,其中 `:id` 是一个路由参数
{
path: '/user/:id',
name: 'User',
component: UserComponent
}
在这个例子中,:id 是一个路由参数,它匹配路径中的任何内容,并将其作为 id 属性传递给 UserComponent 组件。
在组件内部,你可以使用 useRoute 函数(Vue Router 4 的 Composition API)或 this.$route(Vue Router 3 的 Options API)来访问当前路由的状态,包括路由参数。例如:
<script setup>
import { useRoute } from 'vue-router';
const route = useRoute();
// 访问路由参数
const userId = route.params.id;
</script>
需要注意的是,当你使用 params 进行导航时,这些参数不会出现在 URL 的查询字符串(query string)中,而是作为路径的一部分。这与使用 query 参数进行导航是不同的,query 参数会出现在 URL 的 ? 后面,例如 /user?id=123
在category.js文件中封装getCategoryAPI函数并添加请求地址和请求参数:
效果图展示:
(2)useRoute函数
作用:
1.这个函数的作用是在组件内部访问当前路由的状态,包括路由参数、查询参数、路径等信息。
2.useRoute
函数返回一个路由对象,该对象包含当前路由的各种属性和方法。
3.请注意,useRoute只能在组件的setup函数或<script setup>块中使用,因为它依赖于组件的上下文来确定当前路由。如果你尝试在全局作用域或任何非组件上下文中使用它,你将得到一个错误。此外,由于useRoute
返回的是一个响应式对象,当路由发生变化时(例如,用户导航到另一个页面或参数发生变化),该对象将自动更新,以反映当前路由的新状态。这意味着你可以在模板或计算属性中直接使用route
对象的属性,并且它们会在路由变化时自动更新。
例:
<script setup>
import { useRoute } from 'vue-router';
const route = useRoute();
// 现在你可以访问route对象中的任何属性
console.log(route.path); // 打印当前路由的路径
console.log(route.params); // 打印当前路由的参数对象
console.log(route.query); // 打印当前路由的查询参数对象
</script>
(3)watchEffect函数
作用:watchEffect 会在组件渲染时立即执行一次提供的回调函数,并自动追踪回调函数中使用的响应式状态。当这些响应式状态发生变化时,回调函数会被重新执行。它非常适合于执行一些需要在响应式状态变化时自动更新的逻辑
接着,在rabbit-shop\src\views\Category路径下的index.vue文件中把"居家"二字改为插值语法{{categoryData.name}}:
后在rabbit-shop\src\views\Category路径下的index.vue文件中把onMounted函数的调用语句删除,从apis/category.js中导入封装好的getCategoryAPI函数,导入onMounted,ref,watchEffect函数,导入useRoute函数,并在watchEffect函数中调用getCategoryAPI函数,声明一个router变量名把useRouter()函数赋值给route,拿到res,打印res,检查是否成功拿到数据,定义一个数组categoryData,把res中拿到的结果赋值给categoryData,并打印categoryData:
分别在LayoutHeader.vue文件和LayoutFixed.vue文件中<Router-Link>标签中加入active-class="active",如下图所示:
在Category文件夹下的index.vue文件中,复制粘贴以下代码:
<!-- 商品列表 -->
<div class="sub-list">
<h3>全部分类</h3>
<ul>
<li>
<RouterLink to="/">
<img/>
<p></p>
</RouterLink>
</li>
</ul>
</div>
<div class="ref-goods" >
<div class="head">
<h3>- -</h3>
</div>
<div class="body">
<goods-item ></goods-item>
</div>
</div>
(4)数组.数组(例:categoryData.children)
作用:看以下例子可知
又因为右键数据库点击检查显示的children数组是在categoryData数组之下的数组所以在渲染时应用下图代码:
再根据浏览器右键检查显示的数组名对Category文件夹下的index.vue文件进行插值语法处理:
效果图展示:
再次对Category文件夹下的index.vue文件进行插值语法处理:
接着,在Category文件夹下的index.vue文件中导入并使用<goods-item>组件:
然后,再根据浏览器右键检查显示的数组名对商品进行渲染:
最后,对在Category文件夹下的index.vue文件中的样式添加height值:
rabbit-shop\src\views\路径下的
Category文件夹下的index.vue文件总代码:
效果图展示:
点击上图红框内的商品栏均会分别展示出以下样式: