效果流程
- 我们在vue项目中views中创建两个组件一个购物页,一个购物车
- 我们通过localStorage本地储存,来实现页面刷新不掉
- 使用Vuex来进行传值
- 使用Tap来实现切换和是筛选
- 给我们加入购物画册女页的数据添加状态,判断是否选中
- 通过状态来判断选中删除
代码实现流程
Vuex代码逻辑实现:
首先在vuex中通过localStoage来拿取本地数据,先创建一个空对象,来存放拿取的数据,在创建一个来访,我们添加购物车的数据,在创意两个空数组来存放我们的总价和总数量
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state:{
goodsData:[],
cartData:[],
totalMount:0,
totalPrice:0,
},
getters:{
},
mutations:{
SET_DOODS_DATA(state,data){
const {goodsData}=data;
state.goodsData=goodsData;
},
SET_CART_DATA(state,data){
const {cartData,totalmount,totalprice}=data
state.cartData=cartData
state.totalMount=totalmount
state.totalPrice=totalprice
},
},
actions:{
setDoodsData({commit}){
const goodsData=JSON.parse(localStorage.getItem('goodsData'))||[];
commit('SET_DOODS_DATA',{goodsData})
},
setCratData({commit}){
const cartData=JSON.parse(localStorage.getItem('cartData'))||[];
const totalmount=JSON.parse(localStorage.getItem('totalmount'))||0;
const totalprice=JSON.parse(localStorage.getItem('totalprice'))||0;
commit('SET_CART_DATA',{
cartData,
totalmount,
totalprice,
})
},
},
modules:{
}
})
购物页效果实现:
首先页面跳转我们通过路由来实现,然后我们在computed中获取我们商品数据进行渲染,在生命周期函数created中异步拿取数据,让我们刷新之后利己执行,再过我们导航栏的数据加上状态,给它定义一个初始状态,最后通过switch来进行筛选,然后当我们点击加的时候给我们创建的购物车页里面添加数据
代码如下:
<template>
<div class="page">
<header>
<router-link class="acrt" to="/cart">购物车</router-link>
<span class="header-title">商品列表</span>
</header>
<div class="page-list">
<div class="top-wrap">
<ul>
<li :class="{'tab-active':type==item.type}" v-for="item in Type" :key="item.id" @click="type=item.type">{{item.name}}</li>
</ul>
</div>
</div>
<ul class="filter">
<li :class="{'filter-title' :status=='all'}" @click="status='all'">综合排序</li>
<li :class="{'filter-title' :status=='sales'}" @click="status='sales'">销量优先</li>
<li :class="{'filter-title' :status=='priceMax'||status=='priceMin'}" @click="priceMaxMin">价格</li>
</ul>
<ul class="goods-list">
<li class="goods-item" v-for="item in showGoods" :key="item.id">
<div class="goods-img">
<img :src="item.img" alt="item.name">
<!---->
</div>
<div class="goods-info">
<p class="goods-title">{{item.name}}</p>
<p class="goods-price">${{item.price}}</p>
<span class="des">{{item.sales}}人付款</span>
<span class="save" @click="JOIO(item,'ADD')">+</span>
</div>
</li>
</ul>
</div>
</template>
<script>
import { mapState } from 'vuex'
const Type=[
{
id:0,
name:'推荐',
type:0
},
{
id:1,
name:'母婴',
type:1
},
{
id:2,
name:'鞋包饰品',
type:2
},
{
id:3,
name:'食品',
type:3
},
{
id:4,
name:'数码家电',
type:4
},
{
id:5,
name:'居家百货',
type:5
},
]
let boo=true
export default {
data() {
return {
Type,
type:0,
status:'all'
}
},
created() {
this.$store.dispatch('setDoodsData')
},
computed:{
...mapState(['goodsData']),
showGoods(){
let data=null;
if(this.type==0){
data=this.goodsData.map(item=>item);
}else{
data=this.goodsData.filter(item=>item.type==this.type);
}
console.log(data)
switch(this.status){
case "all":
return data
case "sales":
return data.sort((a,b)=>b.sales-a.sales)
case "priceMax":
return data.sort((a,b)=>b.price-a.price)
case "priceMin":
return data.sort((a,b)=>a.price-b.price);
}
}
},
methods: {
priceMaxMin(){
if(boo){
this.status='priceMax'
boo=false
}else{
this.status='priceMin'
boo=true
}
},
JOIO(item,_type){
this.$store.dispatch('setCart',{
id:item.id,
img:item.img,
name:item.name,
price:item.price,
stock:item.stock,
_type
})
}
},
}
</script>
<style lang="less" scoped>
.page{
width: 100%;
header{
line-height: .4rem;
display: flex;
justify-content: center;
align-items: center;
.acrt{
width: .8rem;
text-align: center;
}
.header-title{
padding-left: 20%;
flex: 1;
}
}
.page-list{
.top-wrap{
width: 100%;
height: .6rem;
background: red;
overflow: hidden;
ul{
white-space: nowrap;
overflow-x: scroll;
-webkit-overflow-scrolling: touch;
background-color: #5D4285;
li{
display: inline-block;
width: .8rem;
height: .7rem;
color: #fff;
line-height: .6rem;
text-align: center;
}
.tab-active {
background-color: #9A51FF;
}
}
}
}
.filter{
line-height: .3rem;
display: flex;
justify-content: center;
align-items: center;
li{
flex: 3;
text-align: center;
}
.filter-title{
color: red;
}
}
.goods-list{
width: 100%;
padding-bottom: .45rem;
.goods-item{
margin-top: .1rem;
border-bottom: .05rem solid #ccc;
min-width: .6rem;
.goods-img{
width: .6rem;
height: .6rem;
padding: 0 .1rem;
float: left;
left: 0;
overflow: hidden;
img{
width: 100%;
height: 100%;
}
}
.goods-info{
position: relative;
.goods-title{
width: 70%;
height: 38px;
color: #363636;
line-height: 1.4;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.goods-price{
font-size: 15px;
color: #7a45e5;
}
.des{
font-size: 12px;
color: #888;
}
.save{
position: absolute;
right: 10px;
bottom: 2px;
width: 32px;
height: 22px;
background-color: #7a45e5;
font-size: 16px;
line-height: 19px;
text-align: center;
color: #fff;
border-radius: 12px;
overflow: hidden;
}
}
}
}
}
</style>
购物车页效果实现:
我们点击编辑和完成我们在vuex中定义一个布尔值,然后用v-show来实现显示和隐藏,我们要实现刷新不掉,我们在生命周期函数created中获取一边数据,然后我们computed中获取vuex中的数据,我们的总价和总数量,然后methods中计算加减,在通过我们在vuex中定义的布尔值进行删除
代码如下:
<template>
<div class="page">
<header>
<router-link class="acrt" to="/">返回</router-link>
<span class="header-title">购物列表</span>
<span class="header-edit">
<span v-show="failureShow" @click="SET_FAILURE_SHOW(false)">编辑</span>
<span v-show="!failureShow" @click="SET_FAILURE_SHOW(true)">完成</span>
</span>
</header>
<ul class="cart-list">
<li class="cart-item" v-for="item in cartData" :key="item.id">
<div class="cart-icon" :class="{'select-active':item.select}">
<input type="checkbox" @click="aaa(item)">
</div>
<div class="cart-img">
<img :src="item.img" alt="item.name">
</div>
<div class="cart-info">
<p class="cart-title">{{item.name}}</p>
<p class="cart-price">${{item.price}}</p>
<p class="cart-des">库存{{item.stock}}件</p>
<div class="cart-subtract">
<p class="cart-save" @click="addAND(item.id,item.price,item,'ADD')">+</p>
<p class="cart-save">{{item.mount}}</p>
<p class="cart-save" @click="addAND(item.id,item.price,item,'AND')">-</p>
</div>
</div>
</li>
</ul>
<div class="action-bar">
<div class="item-selector">
<div class="action-icon" :class="{'select-active': tSelect }">
<input type="checkbox" v-model="tSelect">
</div>
<span>全选</span>
</div>
<div class="total">
合计:<span>¥{{totalPrice}}</span>
</div>
<div class="action-btn" v-show="failureShow">去结算({{totalMount}})</div>
<div class="action-btn del-btn" v-show="!failureShow" @click="delectData">删除({{totalMount}})</div>
</div>
</div>
</template>
<script>
import { mapActions, mapMutations, mapState } from 'vuex'
export default {
created() {
this.$store.dispatch('setCratData')
},
computed:{
...mapState(['cartData','totalMount','totalPrice','failureShow']),
tSelect:{
get(){
const boo=this.cartData.every(item=>item.select);
// localStorage.setItem('totalSelect',boo);
return boo;
},
set(value){
console.log(value);
this.$store.dispatch('setTotalSelect',value)
}
}
},
methods: {
...mapMutations(['SET_FAILURE_SHOW']),
...mapActions(['delectData','setTotal']),
addAND(id,price,item,_type){
if(item.select){
if(_type=="ADD"){
this.setTotal({
select:item.select,
Price:item.price,
mount:1
});
}else if(_type=="AND"){
if(item.mount>1){
this.setTotal({
select:item.select,
Price:-item.price,
mount:-1
});
}
}
}
this.$store.dispatch('setCart',{
id,
price,
_type
});
},
aaa(item){
console.log(item)
this.$store.dispatch('setSelect',item.id);
this.$store.dispatch('setTotal',{
select:item.select,
Price:item.Price,
mount:item.mount
})
}
},
}
</script>
<style lang="less" scoped>
.page{
max-width: 12rem;
min-width: .32rem;
header{
width: 100%;
line-height: .4rem;
display: flex;
justify-content: center;
align-items: center;
.acrt{
width: .8rem;
text-align: center;
}
.header-title{
text-align: center;
flex: 1;
}
.header-edit{
width: .8rem;
text-align: center;
}
}
.cart-list{
width: 100%;
padding-bottom: 1rem;
.cart-item{
margin-top: .1rem;
border-bottom: .05rem solid #ccc;
min-width: .6rem;
.cart-icon{
position: relative;
margin: .16rem auto 0 .1rem;
width: .16rem;
height: .16rem;
border-radius: 50%;
border: .02rem solid red;
cursor: pointer;
float: left;
z-index: 1;
input{
width: .16rem;
height: .16rem;
opacity: 0;
}
}
.select-active{
background-color: red;
}
.cart-img{
width: .6rem;
height: .6rem;
padding: 0 .1rem;
float: left;
left: 0;
overflow: hidden;
img{
height: 100%;
}
}
.cart-info{
position: relative;
.cart-title{
width: 60%;
height: 38px;
color: #363636;
line-height: 1.4;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.cart-price{
font-size: 15px;
color: #7a45e5;
}
.cart-des{
font-size: 12px;
color: #888;
}
.cart-subtract{
position: absolute;
right: 10px;
top: 4px;
width: 32px;
color: #999;
text-align: center;
.cart-save{
width: 100%;
height: 24px;
font-size: 20px;
line-height: 20px;
cursor: pointer;
}
}
}
}
}
.action-bar{
line-height: 0.3rem;
display: flex;
justify-content: center;
align-items: center;
padding-bottom: 50px;
position: fixed;
bottom: 0;
width: 100%;
background-color: #fff;
.item-selector{
flex: 1;
line-height: .5rem;
.action-icon{
position: relative;
margin: .16rem .1rem 0 .1rem;
width: .16rem;
height: .16rem;
border-radius: 50%;
border: .02rem solid #ccc;
cursor: pointer;
float: left;
input{
width: .16rem;
height: .16rem;
opacity: 0;
}
}
.select-active{
background-color: red;
}
}
.action-btn{
width: 120px;
height: 100%;
color: #fff;
text-align: center;
font-weight: 300;
line-height: 52px;
cursor: pointer;
background-color: #7A45E5;
}
.del-btn{
background-color: #FF4069;
}
.total{
color: #363636;
font-size: 14px;
line-height: 50px;
margin-right: 20px;
span{
color: red;
}
}
}
}
</style>
写的不太详细以后会努力写详细的
|