目录
一、效果图
1.首页效果图
2.分类
3.购物车
4.我的
5.登录注册
6.商品详情
7.搜索
二、项目实现
1.项目结构、设计说明
2.路由配置实现
3.首页实现源码
4.登录注册实现,模拟登录注册流程,用户数据存储到本地浏览器缓存
三、总结
一、效果图
1.首页效果图
小米官方效果图:
作品demo效果图:
2.分类
3.购物车
4.我的
5.登录注册
6.商品详情
7.搜索
二、项目实现
1.项目结构、设计说明
项目以vue项目创建,前端某些元素使用element,项目启动执行的命令为:
- npm install
- npm run dev(当然命令可以修改为npm run serve,没啥区别)
注意:npm install 成功了再执行 npm run dev 启动项目
结构如下截图,项目已经集成和实现了需要请求后端接口的一切功能,所以无须花费精力去考虑前端如何去对接后端和接口,可以把一切精力放在实现前端界面设计上来。
这样不懂后端的伙伴也省心省力,接口请求只需按照模板去copy就好,无非就是get/post/delete/put等请求方式和参数传递的差别,当然不明白的可以细问作者。
项目结构还是分为:顶部+具体功能显示容器+底部,页面存放于src/page目录下,看目录命名就能明白其含义,具体功能页面在views目录下。
路由在router目录中。
路由权限也是很重要的一个功能,为permission.js,所有页面跳转都会经过其拦截,有人问,路由权限有什么用,好说,比如订单页面或个人中心页面吧,肯定是需要登录才能访问的,首页却是无需登录即可访问的,那么就可以在permission.js里面获取登录token,有token即表示已经登录,可以访问订单或个人中心页面,否则跳转登录页等。
项目结构图:
2.路由配置实现
import Vue from 'vue'
import Router from 'vue-router'
import Layout from '@/page/index/index'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/index',
component: Layout,
children: [{
path: '',
name: '主页',
component: () =>
import( /* webpackChunkName: "views" */ '@/views/home/index')
}]
},
{
path: '/',
name: '主页',
redirect: '/index'
},
{
path: '/type',
component: Layout,
children: [{
path: '',
name: '分类',
component: () =>
import( /* webpackChunkName: "views" */ '@/views/type/index')
}]
},
{
path: '/cart',
component: Layout,
children: [{
path: '',
name: '购物车',
component: () =>
import( /* webpackChunkName: "views" */ '@/views/cart/index')
}]
},
{
path: '/user',
component: Layout,
children: [{
path: '',
name: '我的',
component: () =>
import( /* webpackChunkName: "views" */ '@/views/user/index')
}]
},
{
path: '/address',
name: '收货地址',
component: () =>
import( /* webpackChunkName: "page" */ '@/views/address/index'),
},
{
path: '/login',
name: '登录/注册',
component: () =>
import( /* webpackChunkName: "page" */ '@/views/login/index'),
},
{
path: '/search',
name: '搜索',
component: () =>
import( /* webpackChunkName: "page" */ '@/views/search/index'),
},
{
path: '/setting',
name: '设置',
component: () =>
import( /* webpackChunkName: "page" */ '@/views/user/setting'),
},
{
path: '/productDetail',
name: '商品详情',
component: () =>
import( /* webpackChunkName: "page" */ '@/views/product/detail'),
}
]
})
3.首页实现源码
<template>
<div style="font-size: 14px;" id="home-main">
<div id="product-list">
<div id="product-nav">
<a v-for="(item,index) in topTypes" :key="index" @click="toType(item)">
<p>{{item.name}}</p>
</a>
</div>
<a @click="toType" class="" id="product">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAACu0lEQVRoQ+1YS4sTQRD+ejogRFBB8P1YEE9eVnHxKOrBF4oX9xZE0En3QLyKLLK7vyEmNSMEvHkIKPiIHjx40pOKggviogdlPeniNWSmZGCFyaRncRkzkyzTx0q66vvqK6aqS2DMjxhz/CgI5K1goUChQMoMFCWUMoGprw8ooLW+DGAWwD4A75n5tuu6L1NHGpKDPgJKqVkhxFw8VhAEhzzPW4jbbds+ZlnWmSFhG3ArhFgolUqv6/X6978/9hHQWr8DMGkA1CKia1F7rVbb4Pv+K2Y+khWBlTiPiehiEoFlAFvigJi547ru+RiBA71ebzFj8GG4JSLanUTgEYALBgJzruvOx+1aaw+AnSGJj8zcjmLpK6GwpqWUDwDsioB6Q0RHMwS5plADXyHbtndalnUawFYAn1zXfbImjxn/uWhkGSd88NOaN4C08ddnCTmOs5eZtwH4QkRhbxjZY5qF+noBMxt7wKgw+qdZCMA0EbXjoKvV6ikpZY2Zw89uZ8ikpsKJQEo502g0fho7sVLqmxBijwFIm4imo/awX0gpl4YM2uT+ORGdTRolvgKYiN8SQtxrNptXo3bHcXYw848cCDwjonNJBJJmmyoR3Y2DVUqdFELUAAy9hJh5SgjR6Xa7M61W65eRQGg0vAmM9Z9D5o0hjX1AKTURBMF23/c/R9mOCugojvXZyEYx00mYCgXyVivpQXMcQPjuHK8HjeM4k8z8dGyflFrrhwAuxcsiaaDTWt8EcAvA5sid3/+5rKK+wy2IJqIXSZ04DL7JQGBgrbKiVrhHyvosEtHBJALGxZYQ4k6z2QxHhr6jtX4L4HDGDOpEdMNIIGm1yMwnTPvRSqWysVwuX8mQwLLnefdX7cSR5e5+AB+CILhu2otmCHrVUEUjy1uJQoFCgZQZKEooZQJTXy8USJ3ClA7+AGId+TEiLZB/AAAAAElFTkSuQmCC">
</a>
</div>
<div>
<el-carousel height="207px">
<el-carousel-item v-for="(item,index) in banners" :key="index">
<el-image
style="width: 100%;height: 207px;"
v-if="item"
:src="item"
fit="fit">
</el-image>
</el-carousel-item>
</el-carousel>
</div>
<div id="home-nav">
<div class="home-nav" v-for="(item1,index1) in types" :key="index1+'_1'">
<a v-for="(item2,index2) in item1" :key="index2+'_2'" @click="toType(item2)">
<img :src="item2.img">
</a>
</div>
</div>
<div class="recommend">
<a @click="productDetail" class="">
<img src="../../../public/img/8413c40c709976450cce66a567d13236.jpg" alt="热门推荐" style="width: 100%;">
<p>热门推荐</p>
</a>
</div>
<div class="component-list-main">
<div v-for="(item1,index1) in products" :key="index1" class="list_two_type13 box-flex" style="background: rgb(255, 255, 255);">
<a v-for="(item2,index2) in item1" :key="index2+'_2'" @click="productDetail(item2)" class="exposure item">
<div class="img">
<img class="big" :src="item2.img">
<!---->
<!---->
</div>
<div class="info bgw align-center">
<div class="name">{{item2.name}}</div>
<div class="brief">{{item2.des}}</div>
<div class="price">{{item2.price}}<span>起</span>
<!---->
</div>
<div class="buybtn mauto"> 立即购买</div>
</div>
</a>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
banners:[//轮播图
require('../../../public/img/fac6082a5a2e27bf003163c8ea9ae150.jpg'),
require('../../../public/img/387d1bad240308862741ced9bcaf2f2a.jpg'),
require('../../../public/img/6e95960cdf5776933de70392441d6357.jpg'),
require('../../../public/img/744dd4674e7e07fbd763fb7e98e753a6.jpg')
],
topTypes:[//顶部分类
{id:1,name:'推荐'},
{id:2,name:'智能'},
{id:3,name:'电视'},
{id:4,name:'家电'},
{id:5,name:'冰箱'},
{id:6,name:'洗衣机'},
{id:7,name:'空调'},
{id:8,name:'手机'}
],
types:[//分类
[
{id: 1,name:'米金商城',img: require('../../../public/img/b1749080cf5bbc4dfebff83013bbebaf.jpg')},
{id: 2,name:'小米众筹',img: require('../../../public/img/eb5024fe-dfe3-6e53-3e18-675bef5fa06e.jpg')},
{id: 3,name:'手机',img: require('../../../public/img/69c250436545049ccab81c3e32033cf2.jpg')},
{id: 4,name:'以旧换新',img: require('../../../public/img/e8bc849a-0a3b-21a0-6810-7da3a3903dee.jpg')},
{id: 5,name:'小米上新',img: require('../../../public/img/0434594382110f3bd15c90f040d5d542.jpg')}
],
[
{id: 6,name:'智能',img: require('../../../public/img/64f3988b6216e4c1ab62a7f50df3e816.jpg')},
{id: 7,name:'笔记本热卖',img: require('../../../public/img/9ea68dee2bfa0e55a82236b0d968e975.png')},
{id: 8,name:'电视热卖',img: require('../../../public/img/96c780016ea196743905dc93f9249c39.png')},
{id: 9,name:'洗衣机热卖',img: require('../../../public/img/9425031cdd7af22d9a23a5ae16d1f57c.jpg')},
{id: 10,name:'米粉卡',img: require('../../../public/img/f11f9df6b0b0b428f8c8fc3267131830.png')}
]
],
products:[
[
{name:'Xiaomi 13 Ultra',des:'徕卡光学全焦段四摄| 一英寸可变光圈| 徕卡专业街拍模式',img:require('../../../public/img/202304171628_6486482f87e32aa3b03cfab5928831b0.jpg'),price:5999},
{name:'Redmi Note 12 Turbo',des:'狂暴引擎 超强性能释放',img:require('../../../public/img/202303281131_cf3ff6ce70177560f3b9f95bd48fc575.jpg'),price:1899}
],
[
{name:'Xiaomi 13 Ultra',des:'徕卡光学全焦段四摄| 一英寸可变光圈| 徕卡专业街拍模式',img:require('../../../public/img/202304171628_6486482f87e32aa3b03cfab5928831b0.jpg'),price:5999},
{name:'Redmi Note 12 Turbo',des:'狂暴引擎 超强性能释放',img:require('../../../public/img/202303281131_cf3ff6ce70177560f3b9f95bd48fc575.jpg'),price:1899}
],
[
{name:'Xiaomi 13 Ultra',des:'徕卡光学全焦段四摄| 一英寸可变光圈| 徕卡专业街拍模式',img:require('../../../public/img/202304171628_6486482f87e32aa3b03cfab5928831b0.jpg'),price:5999},
{name:'Redmi Note 12 Turbo',des:'狂暴引擎 超强性能释放',img:require('../../../public/img/202303281131_cf3ff6ce70177560f3b9f95bd48fc575.jpg'),price:1899}
]
]
};
},
mounted() {
this.$store.commit('SET_HEADER_FOOTER', {showIndexHeader: true,headerName:'首页',pageName:'index',showFooter: true});
},
methods: {
toType(){//跳转分类
this.$router.push({'path': '/type'});
},
productDetail(item){//商品详情
this.$router.push({path:'/productDetail'})
}
}
};
</script>
4.登录注册实现,模拟登录注册流程,用户数据存储到本地浏览器缓存
实现逻辑源码:
<script>
import {getStore,setStore} from "@/utils/store.js";
import { setToken } from '@/utils/auth';
export default {
data() {
return {
modalType: 'login',
defaultAvatar: require('../../../public/img/avatar.jpg'),//注册默认头像
loginForm: {
username:'',//用户名
password: "",//密码
},
registerForm: {
username:'',//用户名
password: "",//密码
confirmPassword: "",//确认密码
},
userInfo:{},
userList:[],//全部用户列表
showTip: false,//验证提示
tip: ''//提示语
};
},
mounted() {
},
methods: {
goBack(){//返回
this.$router.go(-1)
},
clearTip(){
this.showTip = false;
this.tip = '';
},
resetForm(){//重置
this.loginForm = {
username:'',
password: ""
};
this.registerForm = {
username:'',
password: "",
confirmPassword: ""
};
this.showTip = false;
this.tip = '';
},
changeModalType(type){//切换登录、注册
this.modalType = type;
this.resetForm();
},
handleLogin() {//登录
let that = this;
that.tip = '';
that.showTip = false;
that.userInfo = {};
if(that.loginForm.username.trim() === ''){
that.tip = '账号名不能为空';
that.showTip = true;
return;
}
if(that.loginForm.password.trim() === ''){
that.tip = '密码不能为空';
that.showTip = true;
return;
}
const loading = that.$loading({
lock: true,
text: '登录中,请稍后。。。',
spinner: "el-icon-loading"
});
//获取所有用户
let userList = getStore({name:'userList'});
if(userList){
that.userList = userList;
let hadUser = false;//循环拼单是否存在用户
that.userList.forEach((item,index)=>{
if(item.username === that.loginForm.username && item.password === that.loginForm.password){
hadUser = true;
that.userInfo = item;
//模拟登录用户 存到缓存
that.$store.commit('SET_USER_INFO', that.userInfo);
//设置登录token
setToken(that.userInfo.id);
that.$notify({
title: '提示',
message: '登录成功',
type: 'success'
//duration: 0//为0则不会自动关闭
});
loading.close();
that.$router.push({'path':'/user'});
}else if(index === (that.userList.length - 1) && !hadUser){
that.$message.warning('账号或密码错误');
loading.close();
}
});
}else{
that.$message.warning('账号或密码错误');
loading.close();
}
},
handleRegister() {//注册
let that = this;
that.tip = '';
that.showTip = false;
if(that.registerForm.username.trim() === ''){
that.tip = '账号名不能为空';
that.showTip = true;
return;
}
if(that.registerForm.password.trim() === ''){
that.tip = '密码不能为空';
that.showTip = true;
return;
}
if(that.registerForm.confirmPassword.trim() === ''){
that.tip = '确认密码不能为空';
that.showTip = true;
return;
}
if(that.registerForm.password.trim() !== that.registerForm.confirmPassword.trim()){
that.tip = '两次输入密码不一致';
that.showTip = true;
return;
}
const loading = that.$loading({
lock: true,
text: '注册中,请稍后。。。',
spinner: "el-icon-loading"
});
//获取所有用户
that.userList = getStore({name:'userList'});
if(!that.userList){
that.userList = [];
}
let pass = true;
if(that.userList.length === 0){
that.checkUseRegister();
loading.close();
}else{
that.userList.forEach((item,index)=>{
if(pass){
if(item.username === that.registerForm.username){
that.$message.warning('用户名已存在,请修改');
loading.close();
pass = false;
}
}
if(pass && index === (this.userList.length-1)){
that.checkUseRegister();
loading.close();
}
});
}
},
checkUseRegister(){//注册
//模拟注册用户 存到缓存
let id = this.userList?(this.userList.length + 1):1;//递增id
let userInfo = {
id: id,
username: this.registerForm.username,
phone: this.registerForm.phone,
password: this.registerForm.password,
avatar: this.defaultAvatar
};
this.userList.push(userInfo);
//用户列表 - 存储到缓存
setStore({name:'userList',content: this.userList});
this.$notify({
title: '提示',
message: '注册成功,请登录',
type: 'success',
duration: 2000//为0则不会自动关闭
});
this.modalType = 'login';
}
}
};
</script>
三、总结
后续不定期将不断完善和增加功能页面(数据分离管理、页面数据通讯交互、参数变化等),敬请期待。
关注作者,及时了解更多好项目!
作者主页也有更多好项目分享!
获取源码或如需帮助,可通过博客后面名片+作者即可!
其他作品集合:
- 《vue完美模拟pc版快手,实现短视频,含短视频详情播放》
- 《vue+element实现美观大方好看的音乐网站,仿照咪咕音乐网》
- 《vue实现功能完整的购物商城,商品零食、电商通用商城》
- 《vue+element实现蔬菜、水果、电商商城》
- 《vue+element简单实现电商商城网站,模仿小米电商商城》
- 《vue实现美观大方的动漫、cos、帖子类型网站》
- 《vue实现好看的相册、图片网站》
- 《高度仿PC版《微信读书》,好看的小说、读书网站》
- 《vue+element实现非常好看的鲜花网站商城,页面完整,样式美观》
- 《vue+elementui+springboot前后端分离实现通用商城管理后台》
- 《微信小程序日记、微信小程序个人空间、个人日记》
- 《vue+element模仿腾讯视频电影网站》
- 《vue+element高度仿照QQ音乐,完美实现PC端QQ音乐》
- 《vue+element详细完整实现个人博客、个人网站》
- 《vue+elementui+springboot前后端分离实现学校帖子网站,学校大作业》
- 《vue+elementui实现U袋网-完整版》
- 《vue+element+electron仿微信实现》
- 《vue+element模仿电商商城,前后端分离实现,下单微信扫码支付》
- 《electron+vue+elementui实现类似QQ窗口靠边自动边缘隐藏》
- 《微信小程序仿唯聚时代,微信小程序商城》
- 《jquery+bootstrap完整丰富样式开发框架源码,各种现成样式简单易用》
- 《html+css响应式旅游主题网站模板,旅游网站,企业文化新闻类网站》
- 《css+html各种动态、动画、3D相册等7件套》
- 《仿华为电商商城,官网,华为超级新品日demo,大屏霸气且简洁》
- 《vue+element简单实现商城网站首页,模仿电商商城》
- 《vue+elementui实现非常好看的博客、网站首页,网站模板》
- 《elementui+vue实现经典管理系统布局框架,拿来即用》
- 《简系统登录页模板html+vue+elementui》
- 《vue+elementui完美实现博客、网站、个人网站,高仿“张凯博客”》
- 《vue+elementui完美实现后台管理系统的左、右、顶部菜单布局》
- 《html5+css3实现3D正方体动画相册2种+3D旋转木马立体动画相册+表白文字加动画爱心+炫酷万花筒五件套含音乐》
- 《后端使用springboot+maven+shiro+mybatis+mysql,前端使用H-ui.admin_v3.1.3.1,快速实现管理后台功能》
- 《springboot+thymeleaf+maven+html+css实现精美大方好看官网模板完整源码》
- 《html+css实现好友列表,类似QQ群聊成员列表》