store.js
let store=new Vuex.Store({
state: {
token:'',
cartarry:JSON.parse(localStorage.getItem('cartarry')) || [],//存储购物车商品的数组
},
mutations: {
//设置vuex的token
settoken(state,token){
state.token=token
},
//添加商品到购物车
tocart(state,tag){
let goods=state.cartarry.find(v=>v.title==tag.label)
if(goods){
goods.cartCount+=1
}else{
state.cartarry.push({title:tag.label,cartCount:1})
}
},
//购物车商品数量加一
cartadd(state,index){
state.cartarry[index].cartCount++
},
//购物车商品数量减一
cartremove(state,index){
if(state.cartarry[index].cartCount>1){
state.cartarry[index].cartCount--
}else{
if(window.confirm('确定从购物车移除商品吗?')){
state.cartarry.splice(index,1)
}
}
},
//清空购物车
clearcart(state){
state.cartarry=[]
}
},
actions: {
},
//相当于我们vue 计算属性
getters:{
countsum:state=>{
let num=0
state.cartarry.forEach(v=>{
num+=v.cartCount
})
return num
}
}
})
//监听每次调用mutations的时候,都会进这个方法,然后我们可以做一些自己想做的处理
store.subscribe((mutations,state)=>{
localStorage.setItem('cartarry',JSON.stringify(state.cartarry))
})
export default store
Botnav.vue
<template>
...
<span class="countsum">{{countsum}}</span>
...
</template>
<script>
import {mapGetters} from 'vuex'
computed:{
...mapGetters({
countsum:'countsum'
})
},
</script>
.countsum
position fixed
bottom 33px
right 23%
z-index 1001
width 18px
height 18px
line-height 18px
border-radius 50%
font-size 14px
background red
color #fff
List.vue
<template>
......
<cube-scroll class="rightpanels">
<ul>
<li v-for="(tag,index) in tags" :key="index">
<img :src="tag.image" alt="">
<p>{{tag.label}} <i class="cubeic-add" @click="addtocart($event,tag)"></i></p>
</li>
</ul>
</cube-scroll>
......
<div class="ball-wrap">
<transition
@before-enter="beforeEnter"
@enter="enter"
@afterEnter="afterEnter"
>
<div class="ball" v-if="ball.show">
<div class="inner">
<i class="cubeic-add"></i>
</div>
</div>
</transition>
</div>
......
</template>
//添加商品到购物车
addtocart(e,tag){
this.$store.commit('tocart',tag)
//让我们小球显示出来
this.ball.show=true
//获取点击元素
this.ball.el=e.target
},
beforeEnter(el){
//让小球移动到点击的位置
//获取点击位置
const dom=this.ball.el
console.log(dom)
const rect=dom.getBoundingClientRect()//获取点击的dom的位置
console.log(rect)
const x=rect.left-window.innerWidth*0.7
const y=-(window.innerHeight-rect.top)
console.log(x,y)
el.style.display='block'
el.style.transform=`translate3d(0,${y}px,0)`
const inner=el.querySelector('.inner')
inner.style.transform=`translate3d(${x}px,0,0)`
},
enter(el,done){
//触发重绘
document.body.offsetHeight
//小球移动回到原点,就是购物车的位置
el.style.transform=`translate3d(0,0,0)`
const inner=el.querySelector('.inner')
inner.style.transform=`translate3d(0,0,0)`
//过渡完成后执行的事件
el.addEventListener('transitionend',done)
},
afterEnter(el){
//结束隐藏小球
this.ball.show=false
el.style.display='none'
}
<style lang="stylus" scoped>
......
.ball-wrap
.ball
position fixed
left 70%
bottom 10px
z-index 1003
color red
transition all 1s cubic-bezier(0.49,-0.29,0.75,0.41)
.inner
width 16px
height 16px
transition all 1s linear
......
.rightpanels
width 70%
ul
...
li
...
.cubeic-add
font-size 18px
</style>
Cart.vue
<template>
<div>
<div class="goods" v-for="(item,index) in cartarr" :key="index">
{{item.title}}
<div class="goodsright">
<i class="cubeic-remove" @click="removeCart(index)"></i>
<span>{{item.cartCount}}</span>
<i class="cubeic-add" @click="addCart(index)"></i>
</div>
</div>
<cube-button style="margin:10px 0;">下单</cube-button>
<cube-button @click="clearcart">清空购物车</cube-button>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
data(){
return{
// cartarr:[]
}
},
computed:{
...mapState({
cartarr:state=>state.cartarry
})
},
methods:{
//减少商品
removeCart(index){
this.$store.commit('cartremove',index)
},
//增加商品
addCart(index){
this.$store.commit('cartadd',index)
},
//清空购物车
clearcart(){
this.$store.commit('clearcart')
}
}
}
</script>
<style lang="stylus" scoped>
.goods
padding 10px
text-align left
.goodsright
float right
i
font-size 18px
</style>
Mine.vue
<template>
<div>
<img class="headerimg" src=" /learn.png" alt="">
<ul>
<li v-for="item in minearry" class="mineitem"
@click="itemclick(item)" :key="item.label">
<span class="minetitle">{{item.label}}</span>
<i class="cubeic-arrow"></i>
</li>
</ul>
</div>
</template>
<script>
export default {
data(){
return{
minearry:[
{label:'商品收藏'},
{label:'我的足迹'},
{label:'店铺收藏'},
{label:'我的订单'},
{label:'退出',type:'exit'},
]
}
},
methods:{
itemclick(item){
if(item.type=='exit'){
this.$store.commit('settoken','')
localStorage.removeItem('token')
this.$router.push({path:'/login'})
}
}
}
}
</script>
<style lang="stylus" scoped>
.mineitem
font-size 14px
text-align left
height 50px
line-height 50px
padding-left 5%
border-bottom 1px solid #eee
.minetitle
display inline-block
width 90%
.headerimg
height 150px
width 100%
</style>
分类演示效果
购物车演示效果
我的购物车演示效果