vuex购物车的实现具体流程

过程分析

1.首先购物车弹窗是一个组件,因为会出现在不同的页面中。

2.因为很多组件会用到购物车数据,所以统一放到vuex中。

实现步骤解析

一、加入购物车

将购物车数据统一放在vuex中:

state里放置一个数组:carPanelData,里面放置购物车数据。

// 购物车商品数据

state: {    

    carPanelData: []

}

往购物车里push数据:在mutation里面更改state数据。

思路:首先需要将点击加入购物车的每一条数据加一个属性:count,计数,然后将这条点击的商品数据push到state中,当然,首先是需要先用商品ID和state里的商品ID比对,如果没有就push,如果有了,就计数。

以下是代码思路

mutations:addCarPanelData(state,加入购物车的数据data){

//循环carPanelData购物车数据//如果商品ID存在(购物车的id和传进来的ID比对),就设置count++

//设置开关false===================================================================   **注意** : 如果上面的条件成立,以下是不执行的,所以可以设置一个开关bOff

//如果开关值为true//否则就是商品ID不存在,设置一个新的变量goodsData = 传进来的data;

//Vue.set(goodsData,'count',1):为这个变量设置count属性,值为1;

//将这个goodsData,push到carPanelData中;              

}

mutations: { 

addCarPanelData (state,data) {

let bOff =truestate.carPanelData.forEach((goods) =>{

                                        if(goods.sku_id === data.sku_id) {          

                                                    goods.count++         

                                                     bOff =false

                                            }      

                })

        if(bOff) {

            let goodsData = data        

            Vue.set(goodsData,'count',1)        

            state.carPanelData.push(goodsData)      

        }

        console.log(state.carPanelData)    

    }  

}

在商品页选择了商品,点击加入购物车按钮:这时,将这条数据传给vuex,记录到state中(mutation里面已经对该逻辑进行了处理)

要点: 记住vuex的思想,要想改变state,必须提交mutation。

methods:{      

   addCarPanelHandel(data){

                //改变state,必须提交mutation,并将此条数据传给 vuex

                this.$store.commit('addCarPanelData',data)       

         }

}

这时已经基本完成了购物车的逻辑,下面,我们把购物车单独出来做成组件:car-panel。

这个时候就可以把相关数据绑定在购物车了。

要点:如何获取在购物车组件内获取vuex数据?

用computed即可。

//相应的绑定代码=示例{{item.title}})

//获取vuex数据

computed : {        

            carPanelData(){

                    return this.$store.state.carPanelData        

            },        

            count(){

                        return this.$store.getters.totleCount        

            },        

            totle(){

                    return   this.$store.getters.totlePrice            

            }

}

最后,对购物车中的商品数量和商品总价计算。

在vue中,我们需要对变量进行进一步处理,可以放在computed里,不建议放在模板中,同样,vuex中,state中的状态如果需要进一步处理,我们可以放入getters.

getters:{

    // 购物车商品数量计算

totleCount (state) {

        let count =0state.carPanelData.forEach((goods) =>{        

                    count += goods.count      

        })

        return  count    

},

// 总价格

totlePrice (state) {

            let price =0state.carPanelData.forEach((goods) =>{        

                    price += goods.price * goods.count     

            })

              return price    

        }  

}

============================================================

至此,已经完成了加购物车,并且计算数量和金额。

============================================================

二、购物车删除

一开始我的思路是

1、删除数据肯定是要改变state,改变state肯定是需要提交mutation,所以删除的相关逻辑方法应该写在mutation;

2、当时我的问题是如何知晓删除的是哪一条数据?

通过学习,弄清楚了,以后此类需求,都和加入购物和思路是一致的,都是通过对比删除的当前的ID和数据里的所有ID进行比对,就知道是删除具体哪条数据了。

3、那么我需要记住,当前选择的是哪条数据,都是通过在删除的点击方法对应的事件里,参数中传递当前数据(商品ID)即可。这是一个思路,需要牢记

具体实现步骤总结

点击购物车页面的删除商品按钮,绑定一个删除方法,参数传入当前被点击的商品ID,在这个方法里调用mutation里面的删除商品方法:

首先需要循环state的购物车数据;

比对每一项的商品ID是否和当前传入的ID相同,如果是相同的那么就return,不再继续循环了;

在state的购物车数据里删除这项ID相同的数据。

//mutation 

  delCarPanelData (state,id) {  

            state.carPanelData.forEach((goods,index) => {

                        if(goods.sku_id === id) {

                              state.carPanelData.splice(index,1)

                                return

                            }      

            })

}

//购物车组件中

    methods: {        

                delCarPanelHandel(id){

                            this.$store.commit('delCarPanelData',id)        

                }

}

删除

三、购物车商品数量限制

思路: 这类显示隐藏的案例,都是设置变量属性的ture/false

首先是有一个弹窗组件,当商品数量大于最大值得时候,这个组件需要弹出。

数据中已经有了最大值 : limit_num。

在state中定义一个变量:maxOff :false ,默认不显示,当购物车中商品增加的时候,比对当前商品的数量是否已经大于了limit_num,如果是,就让这个弹窗出来,也就是在mutation中设置该属性为true。

商品数量超过后显示弹窗

// 加入购物车

addCarPanelData (state,data) {     

             state.carPanelData.forEach((goods) =>{

                        if(goods.sku_id === data.sku_id) {  

                               goods.count++          

                               bOff =false  //比较当前商品的数量和数据中的商品最大购买数量                                                   if(goods.count > goods.limit_num) {           

                                                 goods.count--            

                                                  state.maxOff =true

                                    }       

                         }      

                }) 

}

//组件中

computed: {        

            maxOff(){

                return this.$store.state.maxOff        

            }  

}

关闭弹窗

//mutations

        closePrompt (state) {    

                 state.maxOff =false

        }

//组件中

methods : {     

     closePrompt(){

       this.$store.commit('closePrompt')      

     }  

 }

四、购物车显示隐藏

思路: 一样的,这类显示隐藏,需要设置一个开关,去切换开关即可。

state: {

         carPanelData: [],

          maxOff:false,// 弹窗开关

         carShow :false,// 购物车开关

          carTimer :null// 购物车定时器

   },

// 购物车显示

  showCar (state) {      

     clearTimeout(state.carTimer)      

     state.carShow =true

 },

// 购物车隐藏

hideCar (state) {      

     state.carTimer = setTimeout(()=>{ 

                state.carShow =false

            },1000)    }

//组件中

methods: {

    // 显示购物车

    showCar(){

            this.$store.commit('showCar')       

     },

    // 隐藏购物车

    hideCar(){

            this.$store.commit('hideCar')        

    }

 }

四、购物车小球效果

思路:用的vue的transtion钩子函数,原理就是先把小球写死到购物车,点击的时候瞬间移入到需要的位置,然后做一个过渡动画即可,加入贝塞尔曲线。

state: {

                ball: { // 购物车小球

                                show:false,

                                  el:null,// 点击的是哪个购物车按钮

                                    img:''

              }

}

mutations: {

 // 加入购物车

  addCarPanelData (state,data) {

          // 加上这个条件,确保小球飞完再添加

           if(!state.ball.show){ 

                    // 显示购物车

                      state.carShow =true

                     let bOff =true 

                      state.carPanelData.forEach((goods) =>{

                            // 比对ID,相同就说明购物车已存在此商品,数量增加

                            if(goods.sku_id===data.sku_id) {

                                  goods.count++

                                    bOff = false 

                                    if(goods.count > goods.limit_num) {

                                           goods.count--

                                            state.maxOff = true

                                                    return

                        } 

                        //加入购物车, 小球显示

                        state.ball.show = true

                         state.ball.img = data.ali_image 

                           // 通过event对象获取到当前点击的按钮

                            state.ball.el = event.path[0] 

            } 

        })

            //商品不存在, 就往数组里新增商品数据

          if(bOff) {

                      let goodsData = data Vue.set(goodsData, 'count', 1)                         state.carPanelData.push(goodsData) // 加入购物车,小球显示

                        state.ball.show= true 

                        state.ball.img = data.ali_image 

                        // 通过event对象获取到当前点击的按钮

                        state.ball.el = event.path[0] 

                }

            console.log(event) 

    } 

}

//组件内//

 小球进入前, 初始化

beforeEnter(el) { 

    // 获取按钮的位置

    let rect =this.ball.el.getBoundingClientRect()

    // 获取购物车

     let rectEl =document.getElementsByClassName('ball-rect')[0].getBoundingClientRect()

   //获取小球

    let ball = document.getElementsByClassName('mask-item')[0] 

    //计算按钮和购物车的差值 : 购物车的中心点到左侧的距离 - 按钮中心点到左侧的距离

       let x = (rectEl.left+16) - (rect.left + rect.width / 2) 

       let y = rect.top + rect.height / 2 -rectEl.top + 5 - 16 

        //计算小球和包着小球的父级的位置

        ball.style.transform ='translate3d(-'+x+'px,0,0)'

        el.style.transform= 'translate3d(0,' + y + 'px,0)'

         ball.src = this.ball.imgconsole.log(this.ball.img)

}, 

//开始运动

enter (el){

        let a = el.offsetHeight

        // 获取小球

        let ball = document.getElementsByClassName('mask-item')[0] 

        el.a = a 

         //避免变量没有使用,eslint报错

        el.style.transform ="translate3d(0,0,0)"

        ball.style.transform= "translate3d(0,0,0)"

}, 

// 结束,让小球隐藏

    afterEnter (el){

            this.ball.show =false

    }


.ball-enter-active{ 

            transition:1 s cubic - bezier(.18, 1, .94, 1)

    }

.ball - enter - active.mask - item {

                    transition: 1 s cubic - bezier(0, 0, 0, 0)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容