一、前言
1.本项目基于vant4+vue3构建,默认友友们已具备相关知识,如不具备,请友友们先去了解相关该概念
2.项目数据来源于开源框架 新峰商城 在此指出
3.此项目目的在于帮助友友们了解基本的用法,没有涉及太多的逻辑操作。
二、项目介绍
首页
分类
我的
三、项目搭建
大家可以看看项目所需的依赖,具体的安装命令如下
axios
npm install axios --save
less(为了书写样式方便,不需要强制安装)
npm install less --save
mockjs(使用mockjs制造假数据)
npm install mockjs --save
vant(可以去官网看看组件的使用用法)
npm i vant
vue-router(必须要的哈,进行页面切换的)
npm install vue-router
安装为项目所需的依赖,我们需要将需要的依赖引入我们的项目中
在main.js中引入并使用安装好的vant
创建路由并加载到main.js
路由的配置
注意:路由文件所需要的home、user、cag组件自己先定义好,然后引入到路由文件中,大家也可以使用懒加载的方式,具体组件的创建就不演示了。
四、页面制作
在配置完路由之后,思考我们的配置的路由是做什么的。通常为了页面的切换,我们会需要一个固定在顶部的导航条,我们称之为tabbar,且所有的页面都能看到这个导航条
首页显示
路由配置结束,需要将其显示出来,路由出口配置在app.html页面
在本项目中,我将首页重定向到home页面,所有接下来的所有操作,我们去到home页面
这是home页面的结构,包括搜索框、轮播图、商品分类、商品显示,顶部导航,有经验的小伙伴可以看看view文件夹和components文件夹,这里我将具体的页面放在view下,其余组件拆分放到components
具体显示效果如下
现在我们拆分这个页面
搜索框
代码
<template><van-sticky><van-searchshape="round"background="#1baeae"placeholder="请输入搜索关键词"></van-search></van-sticky></template>
van-sticky为黏性布局,也就是鼠标向下滑动,搜索框会固定在顶部
轮播图(swiper)
代码
<template><van-swipe :autoplay="3000" lazy-render><van-swipe-item v-for="(item,index) in newGoods.carousels" :key="index"><img :src="item.carouselUrl" /></van-swipe-item>
</van-swipe>
</template>
<script setup>import {onMounted,reactive} from "vue"import request from "../mock/request.js"const newGoods = reactive({carousels:[]})onMounted(async() =>{let result = await request({url:'/mock/getGoods',method:'get'})if(result.data.code === 200){newGoods.carousels = result.data.data.carousels}})
</script>
<style type="text/css" media="all" scoped>img{width: 100%;height: 200px;}
</style>
这里大家看看mock中我们写的假的json数据
{"carousels": [{"carouselUrl": "https://res.vmallres.com/uomcdn/CN/cms/2024-05/6580fa613c574939a84e0a04e288292b.jpg","redirectUrl": "https://juejin.im/book/6844733826191589390"},{"carouselUrl": "https://res.vmallres.com/uomcdn/CN/cms/202405/240051cba47c47d384142a253d50cb6d.png","redirectUrl": "https://juejin.im/book/6844733826191589390"},{"carouselUrl": "https://res.vmallres.com/uomcdn/CN/cms/202406/c16311df062d43c49f9e692728b5efd4.jpg","redirectUrl": "https://juejin.im/book/6844733826191589390"},{"carouselUrl": "https://res.vmallres.com/uomcdn/CN/cms/2024-05/1e56a1ce74b8447baaf08b87eaf007ec.jpg","redirectUrl": "https://juejin.im/book/6844733826191589390"}]
}
看看mockserver.js文件,如果小伙伴写过node的话,这里应该很好理解
这里写了三个接口,对于的三个页面数据,轮播图中用的数据都在goods中,在request文件中,只是简单的对超时做了限制
此项目不需要我们我们二次封装axios
了解完这些前置知识和后,我们在认真关注下我们的swiper组件中的内容
认真看完上面教程,给位友友们应该可以将轮播图正确显示出来了
商品分类
代码
<template><van-grid clickable :column-num="5"><van-grid-item to="/cag" v-for="(value,index) in categoryList.list" :key="index" :text="value.name"><van-image :src="value.imgUrl"></van-image><span>{{value.name}}</span></van-grid-item></van-grid></template>
<script setup>import {onMounted,reactive} from "vue"import request from "../mock/request.js"const categoryList = reactive({list:[]})onMounted(async() =>{let result = await request({url:'/mock/getCategoryList',method:'get'})if(result.data.code === 200){categoryList.list = result.data.data}})
</script>
<style type="text/css" media="all" >.van-image__img{width: 50px !important;height: 50px !important;}span{font-size: 20px !important;}
</style>
我们看看这个页面的结构
mock中的数据
商品页面
代码
<template><header class="good-header">新品上线</header><div class="good-box" ><div class="good-item" v-for="item in newGoods.newGoods" :key="item.goodsId" @click="goToDetail(item)"><img :src="item.goodsCoverImg" alt=""><div class="good-desc"><div class="title">{{ item.goodsName }}</div><div class="price">¥ {{ item.sellingPrice }}</div></div></div></div></template>
<script setup>import { useRouter } from 'vue-router'import {onMounted,reactive} from "vue"import request from "../mock/request.js"const router = useRouter();const newGoods = reactive({newGoods:[],hots: [],recommends: [],})onMounted(async() =>{let result = await request({url:'/mock/getGoods',method:'get'})if(result.data.code === 200){newGoods.newGoods = result.data.data.newGoodsesnewGoods.hots = result.data.data.hotGoodsesnewGoods.recommends = result.data.data.recommendGoodses}})const goToDetail = (item) => {router.push({ path: `/product/${item.goodsId}` })}
</script>
<style scoped>.good-header {background: #f9f9f9;height: 50px;line-height: 50px;text-align: center;color: #1baeae;font-size: 25px;font-weight: 500;}.good-box {display: flex;justify-content: flex-start;flex-wrap: wrap;}.good-item {box-sizing: border-box;width: 50%;border-bottom: 1PX solid #e9e9e9;padding: 10px 10px;}.good-item:nth-child(2n + 1) {border-right: 1PX solid #e9e9e9;}img {display: block;width: 120px;margin: 0 auto;}.good-desc {text-align: center;font-size: 20px;padding: 10px 0;}.title {color: #222333;}.price {color:#1baeae;} </style>
代码解释
点击挑转到商品详情
详情页面也是一致的,大家看情况编写。由于涉及到后续的购物车,所有我没有继续往下写了
底部导航
代码
<template><van-tabbar v-model="active" class="bar"> <van-tabbar-item icon="home-o" to="/home">首页</van-tabbar-item><van-tabbar-item icon="search" to="/cag">分类</van-tabbar-item><van-tabbar-item icon="friends-o" to="/user">个人</van-tabbar-item></van-tabbar>
</template><script setup>
import { ref} from "vue"const active = ref('home');
</script>
<style type="text/css" >.bar{margin-top: 40px !important;}.van-tabbar-item{font-size: 16px !important;}
</style>
这里的代码就不做解释了,相信大家都能看懂
将所需要要的组件引入即可
分类页面
分类页面比较简单,经过首页一节的铺垫,现在我们将节奏快点
页面分为上中下三层。上层为搜索框;中间左侧为侧边栏,右边为商品;下层为导航条
代码
<template><TabNav></TabNav><div class="container"><SliderNav></SliderNav><CagGoods></CagGoods></div><div style="width:100%;height:40px"></div><Tabbar></Tabbar>
</template>
<script setup>import Tabbar from "../components/Tabbar.vue"import TabNav from "../components/TabNav.vue"import SliderNav from "../components/SliderNav.vue"import CagGoods from "../components/CagGoods.vue"</script>
<style scoped>.container{display: flex;flex-direction: row;}.container .van-sidebar {flex: 2;}.container .van-grid{flex: 10;}
</style>
这里贴出的代码是为了方便大家布局使用的
顶部导航
侧边栏
右侧goods
我的
<template><div class="user"><Card></Card><div class="box"><van-icon name="setting-o" class="setting"/><span>设置</span></div><div class="box1"><van-icon name="service-o" class="service" ></van-icon><span>联系客服</span></div><MyOrder></MyOrder><MySerive></MySerive></div><Tabbar></Tabbar>
</template>
<script setup>import Tabbar from "../components/Tabbar.vue"import Card from "../components/Card.vue"import MyOrder from "../components/MyOrder.vue"import MySerive from "../components/MySerive.vue"</script>
<style >.user{position: relative;}.van-card__title {font-size: 20px !important;margin-top: 10px;height: 30px !important;line-height: 30px;}.box{display: flex;position: absolute;top: 10px;right: 20px;font-size: 25px;flex-direction: column;}.box1{display: flex;position: absolute;justify-content:center;align-content: center;top: 10px;right: 80px;font-size: 25px;flex-direction: column;}.service{text-align: center;}span{font-size: 12px;}</style>
MyOrder
<template><div class="temp"><div class="top"><span class="order">我的订单</span><span class="all">全部></span></div><div class="content"><div><van-icon name="shop-o" /><span>待付款</span></div><div><van-icon name="gift-card-o" /><span>待发货</span></div><div><van-icon name="setting-o" class="setting"/><span>待收货</span></div><div><van-icon name="chat-o" /><span>待评价</span></div><div><van-icon name="balance-o" /><span>退款/售后</span></div></div></div>
</template>
<script></script>
<style scoped>*{margin: 0;padding: 0;}.temp{display: flex;flex-direction: column;margin-top: 5px;transition: 0.3s;margin: 10px;padding: 10px;border-radius: 5px;background: #1baeae;box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);overflow: hidden;}.temp:hover{box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2);}.top{display: flex;justify-content: space-between;align-content: center;}.order{font-size: 20px;}.all{margin-right: 20px;}.content{display: flex;flex-direction: row;justify-content: center;}.content div{margin-top: 10px;margin-left: 20px;display: flex;flex-direction: column;flex: 1;text-align: center;}.content div span{margin-top: 5px;}
</style>
这里大家掌握flex布局即可写出
MySerive
这个页面其实也是一样的,只是一个横向,一个纵向
写在最后
到这里就算写完了,希望各位友友们可以自己多加思考,清楚掌握。
同时也请大家多多点赞支持