项目效果
后期为了好看就改成滑动删除了和添加了登录和升序降序
提示:可以点击下面的【文章目录】可以跳转到想去的一项例如购物车代码,分类渲染代码
文章目录
前言
1.首页基本布局 【轮播图+搜索框+菜单栏+商品列表】
2.二级路由配置,点击菜单切换
3.分类数据接口请求及数据渲染【本地json文件】
4.首页点击图片进入详情页
5.商品列表数据的渲染及结构布局
6.首页点击分类进行数据筛选
7.点击商品加入购物车,存储到vuex中
8.购物车数据渲染,计算购物车商品总价格全选.反选.删除
9.首页模糊搜索【单独配置一个路由】
10.首页点击返回顶部
11.显示购物车标签已加入的数量
提示:以下是本篇文章正文内容,下面案例可供参考使用
二、使用步骤和router.js文件的配置路由
1.main.js引入库
代码如下(示例):
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import axios from "./http/index"
import Vant from 'vant';
import 'vant/lib/index.css';//引入vant 组件
import ElementUI from 'element-ui'//引入element ui的组件
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI);
Vue.use(Vant);
Vue.config.productionTip = false
Vue.prototype.$axios=axios;
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
在Home页面编写
2.首页分类数据接口请求及数据渲染点击切换和商品列表数据的渲染及结构布局
代码如下(示例):搜索和轮播图在Vant 插入好了,文章底部有完整源代码可以下载
<template>
<div class="replace">
<!-- 标签页 -->
<van-tabs @click="showGoods">
<van-tab v-for="item in classify" :title="item.title" :key="item._id">
</van-tab>
</van-tabs>
<!-- Grid 宫格 -->
<van-grid :column-num="2"><!--注意刚开始v-for里面是all,渲染后在切换成list-->
<van-grid-item v-for="item in list" :key="item._id">
<img :src="item.pic" alt="" />
<p>{{ item.title }}</p>
<p>¥{{ item.price }} <van-icon name="cart-o"/></p>
</van-grid-item>
</van-grid>
</div>
</template>
<script>
export default {
props: [],
data() {
return {//这里存放数据
classify: [], //存储分类内容的
all: [], //存放所有的产品
list: [], //存放的是单个分类的产品
};
},
mounted() {
this.biao();
this.xia();
},
//点击
methods: {
biao() {//分类
this.$axios.get("/fenlei.json").then((res) => {
console.log(res.result);
this.classify = res.result;
});
},
xia() {//所有
this.$axios.get("/list1.json").then((res) => {
console.log(res.result);
this.all = res.result;
this.list = res.result;
});
},
showGoods(i, title) {//切换分类
let id = this.classify[i]._id; // 根据标示符i找到当前点击的分类的id值
console.log(id);
this.list = this.all.filter((item) => { // 根据分类id去all所有的商品中找该分类下的商品
return item.cid === id;
});
},
},
};
</script>
<style scoped>
img {
width: 100px;
height: 100px;
}
</style>
3.Sy首页点击图片进入详情页渲染
<img :src="item.pic" alt="" @click="$router.push('/xqy?_id=' + item._id)"/>
详情页
<template>
<div>
<van-nav-bar title="商品详情" left-arrow @click-left="onClickLeft" />
<img :src="all.pic" alt="" />
<p>{{ all.title }}</p>
</div>
</template>
<script>
export default {
data() {
return {
all: [],//所有
};
},
methods: {
onClickLeft() {
this.$router.push("/sy");
},
},
mounted() {
let id = this.$route.query._id;
console.log(id);
this.$axios.get("list1.json").then((res) => {
let goods = res.result;
console.log(goods);
this.all = goods.find((item) => {
return item._id == id;
});
});
},
};
</script>
4.点击商品加入购物车,并存储到vuex中
在Grid 宫格 下面加弹出层
<!-- 弹出层 -->
<van-popup v-model="show" closeable close-icon="close" position="bottom" :style="{ height: '80%' }">
<van-image :src="join.pic" width="100%" />
<p>{{ join.title }} -- ¥{{ join.price }}</p>
<van-button size="small" @click="jia_gwc">加入购物车</van-button>
</van-popup>
export default {
props: [],
data() {
return { //这里存放数据
show: false,//显示隐藏
join: {}, //加入购物车
};
},
showPopup(item) {
this.show = true;
this.join = item;//获取数据传到good并渲染
},
methods: {//点击
jia_gwc() {
this.$set(this.join, "num", 1);
console.log(this.join);
this.$store.commit("jia_gwc", this.join);
this.$toast.success("加入购物车成功");//提示框
},
},
};
</script>
store.js文件
export default new Vuex.Store({
plugins:[createPer()], //持久存储数据
state: {//存放公共数据 --初始值
shop:[]//购物车数据存储
},
mutations: {
jia_gwc(state,join){
state.shop.push(join)
},
},
})
5.购物车数据渲染,计算购物车商品总价格.全选.反选.删除
1.Gwc购物车页面
<template>
<div class="replace"><!-- 把Vuex的数据渲染到购物车页面 -->
<van-swipe-cell v-for="(item, index) in $store.state.shop" :key="index">
<van-card :num="item.num" :price="item.price" :title="item.title" class="goods-card">
<template #thumb><!-- 单选复选框 -->
<input type="checkbox" @click="changeCheckOne(index)" v-model="item.isCheck"/>
<van-image :src="item.pic" alt="" />
</template>
<template #num><!-- 步进器 实现加加减减功能 -->
<van-stepper theme="round" button-size="22" disable-input v-model="item.num" />
</template>
</van-card>
<template #right><!-- 滑动删除 -->
<van-button square text="删除" type="danger" class="delete-button" @click="$store.commit('sc', index)"/>
</template>
</van-swipe-cell><!-- 计算总价和全选 -->
<van-submit-bar :price="$store.getters.totals * 100" button-text="提交订单">
<van-checkbox v-model="checkedAll" @click="changeAll">全选</van-checkbox>
<template #tip>
你的收货地址不支持同城送, <span>修改地址</span>
</template>
</van-submit-bar>
</div>
</template>
<script>
export default {
data() {
return { //这里存放数据
checkedAll: false,//判断不选中
};
},
methods: {//点击
changeCheckOne(ind) {
this.$store.commit("changeOne", ind);
// 判断数组中所有的是否全部选中,只要有一个不选中 全选按钮就不选中
this.checkedAll = this.$store.state.shop.every((item) => {
return item.isCheck == true;
});
},
changeAll() {//全选
this.$store.commit("changeAll", this.checkedAll);
},
},
created() {
// 页面刷新 给全选按钮赋初始值
this.checkedAll = this.$store.state.shop.every((item) => {
return item.isCheck == true;
});
},
};
</script>
<style lang="scss" scoped>
.goods-card {
margin: 0;
background-color: white;
}
.delete-button {
height: 100%;
}
.van-swipe-cell__wrapper {
border: 1px solid #000;
}
</style>
2.然后再store.js文件夹里写入
import Vue from 'vue'
import Vuex, { Store } from 'vuex'
import createPer from 'vuex-persistedstate'
Vue.use(Vuex)
export default new Vuex.Store({
plugins: [createPer()], //持久存储数据
state: {//存放公共数据 --初始值
shop: []//购物车数据存储
},
mutations: {//把弹出框里的数据存到Vuex里面点击加入购物车后,
//进入购物车页面直接调用渲染就可以了
jia_gwc(state, join) {
state.shop.push(join)
},
sc(state, index) {//删除购物车的数据
state.shop.splice(index, 1);
},
changeOne(state, index) {
// 把当前点击的这条数据的ischeck值取反
state.shop[index].isCheck = !state.shop[index].isCheck
},
changeAll(state, checkall) {
// 改变所有的
state.shop.forEach(item => {
item.isCheck = checkall
})
}
},
getters: {
//计算总价格
totals(state) {
//顶一个初始化的变量
let money = 0;
//循环购物车的数据,计算总价格
state.shop.forEach(item => {
if (item.isCheck == true) {//if判断单选中计算出总价
money += item.num * item.price;
}
})
return money;
},
},
})
6.首页模糊搜索【单独配置一个路由】Ss页面
<template>
<div class="replace">
<van-nav-bar title="搜搜商品" left-arrow @click-left="$router.go(-1)" />
<!-- 头部搜索框 -->
<van-search placeholder="输入搜索的商品名" v-model="keyword" shape="round" />
<van-grid :column-num="2">
<van-grid-item v-for="item in lists" :key="item._id">
<img :src="item.pic" alt="" />
<p>{{ item.title }}</p>
<p>¥{{ item.price }} <van-icon name="cart-o" /></p>
</van-grid-item>
</van-grid>
</div>
</template>
<script>
export default {
props: [],
data() {
return {//这里存放数据
keyword: "",
all: [],
};
},
components: {},
methods: {//点击
xia() {
this.$axios.get("/list1.json").then((res) => {
console.log(res.result);
this.all = res.result;
});
},
},
computed: {//监听属性 类似于data概念
lists: function () {
return this.all.filter((item) => {
return item.title.match(this.keyword);
});
},
},
mounted() {
this.xia();
},
};
</script>
<style scoped>
img {
width: 100px;
height: 100px;
}
</style>
7.首页点击返回顶部
需要安装Element ui插件就可以直接返回顶部了
位置放的底部就好了
<el-backtop :bottom="100">
<div
style="{
height: 100%;
width: 100%;
background-color: #f2f5f6;
box-shadow: 0 0 6px rgba(0,0,0, .12);
text-align: center;
line-height: 40px;
color: #1989fa;
}"
>
UP
</div>
</el-backtop>
8.显示购物车标签已加入的数量vuex
1.首先在主路由设置:badge="$store.getters.nums"
2.然后再store.js中设置
export default new Vuex.Store({
plugins: [createPer()], //持久存储数据
state: {//存放公共数据 --初始值
shop: []//购物车数据存储
},
getters: {
nums(state) {//购物车数量图标
//顶一个初始化的变量
let sl = 0;
//循环购物车的数据,计算总价格
state.shop.forEach(item => {
sl += item.num;
})
return sl;
},
},
})
9.价格升序降序
这个放到标签下面就可以了
<div @click="changeSort">价格{{ flag ? "升序" : "降序" }}</div>
<script>
export default {
data() {
return {//这里存放数据
all: [], //存放所有的产品
flag: true, //判断升序还是降序
};
},
methods: {
//价格升序降序
changeSort() {
if (this.flag) { //升序
this.all.sort(function (a, b) {
return a.price - b.price;
});
} else {//降序
this.all.sort(function (a, b) {
return b.price - a.price;
});
}
this.flag = !this.flag;
},
},
};
</script>
10.路由守卫进入购物车必须登录验证
1.在[我的]Wd页面:代码详情
<template>
<div>
<div v-if="user">
111 {{ user.name }}欢迎你<button @click="loginout">退出</button>
</div>
<div v-else>没有登陆</div>
</div>
</template>
<script>
export default {
data() {
return {
user: {},
};
},
created() {
this.user=sessionStorage.getItem('user')?JSON.parse(sessionStorage.getItem('user')):""
},
methods: {
loginout() {
// 清空本地存储的数据
sessionStorage.removeItem("user");
// 跳转到登陆页面
this.$router.push("/login");
},
},
};
</script>
2.用户名和密码[Login]页面【注意】需要新创建一个路由
<template>
<div>
用户名:<input type="text" v-model="user.name" />
<br/>
密码:<input type="password" v-model="user.pass" />
<br/>
<button @click="loginin">登陆</button>
</div>
</template>
<script>
export default {
data(){
return {
user:{
name:"",
pass:"",
}
}
},
methods:{
loginin(){
// 获取用户名和密码this.user
// 发送服务端 省略
// 把用户信息存储到本地
// JSON.stringify(thisuser)把对象转换为字符串
sessionStorage.setItem('user',JSON.stringify(this.user))
// 跳转到首页
this.$router.push('/sy')
}
}
}
</script>
3.然后再router.js文件夹里面写上判断
router.beforeEach((to, from, next) => {
// 判断是否进入购物车页面
if (to.path === '/gwc') {
// 判断是否登陆
if (sessionStorage.getItem('user')) {
next()
} else {
next('/login')
}
} else {
next()
}
})
总结
上面项目纯属个人搭建,适用于移动端项目
这个移动端的项目相当于已经很完整了基本的功能也实现了
~ 喜欢的小伙伴点个赞呗,评论区留下宝贵的意见-谢谢呐♥~
- 如果文章当中有问题,或者有什么好的意见,大家可以指出来,一起学习。
- 本文版权归作者所有,欢迎转载。
- 需要源码的可以去git下载地址为:https://gitee.com/wang-yu-fen_admin/move