購物車模塊實現

1、購物車列表功能實現

點擊加入購物車或者點擊購物車圖標后進入購物車頁面,在購物車頁面中首先渲染cartList的列表。首先加載init()方法,在init方法中發起get請求,請求cartList數據(不需要傳入參數)。在后端先解析出用戶cookie中的userId,查找文檔,如果找到了就把cartList返回去。
前端實現代碼

data(){
            return{
              cartList:[],
            }
        },
        mounted(){
          this.init();
        },
        methods:{
          init(){
            axios.get('/users/cartList').then((response)=>{
              let res=response.data;
              this.cartList=res.result;
            })
          }
       },
        components:{
            NavHeader,
            NavFooter,
            NavBread,
            Modal
        }
    }

后端實現代碼

//查詢當前用戶的購物車數據
router.get('/cartList',(req,res,next)=>{
    let userId=req.cookies.userId;
    User.findOne({userId:userId},(err,doc)=>{
        if(err){
            res.json({
                status:'1',
                msg:err.message,
                result:''
            })
        }else{
            res.json({
                status:'0',
                msg:'',
                result:doc.cartList
            })
        }
    })
})

2、商品刪除功能

點擊購物車頁面的刪除按鈕,彈出詢問是否刪除的模態框,并用變量productId記錄商品id,點擊模態框上的確認刪除后,向后端發起post請求,傳入參數商品id,后端返回響應后關閉模態框并重新調用init方法重新渲染購物車列表
前端代碼:

data(){
            return{
              cartList:[],
              mdDel:false,
              productId:''
            }
        },
        mounted(){
          this.init();
        },
        methods:{
          init(){
            axios.get('/users/cartList').then((response)=>{
              let res=response.data;
              this.cartList=res.result;
            })
          },
         delPrd(id){
            this.mdDel=true;
            this.productId=id;     
          },
          prdDel(){
            axios.post('/users/delprd',{
              productId:this.productId
            }).then((response)=>{
              let res=response.data;
              if(res.status=='0'){
                this.mdDel=false;
                this.init();
              }
            })
          }
       },
        components:{
            NavHeader,
            NavFooter,
            NavBread,
            Modal
        }
    }

后端代碼:

router.post('/delprd',(req,res,next)=>{
    let userId=req.cookies.userId;
    let pdId=req.body.productId;
    User.update({userId:userId},{$pull:{'cartList':{'productId':pdId}}},(err,doc)=>{
        if(err){
            res.json({
                status:'1',
                msg:err.message,
                result:''
            })
        }else{
            res.json({
                status:'0',
                msg:'刪除成功',
                result:'suc'
            })
        }
    })
})

3、商品修改功能

點擊+-需要和前邊的是否選中需要修改商品數據。
首先加減是在+-的按鈕上調用editCart方法,并傳入商品item和+-的flag(add和minus)如果是+,就給item的productNum++,反之--。如果flag不是+-,就是check了,那此時將item的選中狀態變為相反數。全部改變完之后將數據傳到后端進行同步處理。通過axios的post請求,傳入參數商品id,商品數量,和商品的選中狀態。請求之后如果成功了就好,沒成功的話要把數量變回原值。并彈出提示信息。后端更新子文檔有不同的方法,可以先查找到子文檔在更新,也可以直接更新子文檔。后者比較簡單。
前端更新后的代碼:

data(){
            return{
              cartList:[],
              mdDel:false,
              productId:''
            }
        },
        mounted(){
          this.init();
        },
        methods:{
          init(){
            axios.get('/users/cartList').then((response)=>{
              let res=response.data;
              this.cartList=res.result;
            })
          },
         delPrd(id){
            this.mdDel=true;
            this.productId=id;     
          },
          prdDel(){
            axios.post('/users/delprd',{
              productId:this.productId
            }).then((response)=>{
              let res=response.data;
              if(res.status=='0'){
                this.mdDel=false;
                this.init();
              }
            })
          },
         editCart(item,flag){
            let oldNum=item.productNum;
            if(flag=='add'){
              item.productNum++;
            }else if(flag=='minus'){
              if(item.productNum<=1){
                return;
              }else{
                item.productNum--;
              }   
            }else{
              item.checked*=-1;
            }
            axios.post('/users/changeNum',{
              pdId:item.productId,
              num:item.productNum,
              checked:item.checked
            }).then((response)=>{
              let res=response.data;
              if(res.status!='0'){
                item.productNum=oldNum;
                alert('更改商品數量失敗')
              }
            })
          },
       },
        components:{
            NavHeader,
            NavFooter,
            NavBread,
            Modal
        }
    }

后端代碼:

router.post('/changeNum',(req,res,next)=>{
    let userId=req.cookies.userId;
    let pdId=req.body.pdId;
    let num=req.body.num;
    let checked=req.body.checked;
    //先查找再更新
    // User.findOne({userId:userId},(err,doc)=>{
    //     if(err){
    //         res.json({
    //             status:'1',
    //             msg:err.message,
    //             result:''
    //         })
    //     }else{
    //         doc.cartList.forEach((item)=>{
    //             if(item.productId==pdId){
    //                 item.productNum=num;        
    //             }
    //         });

    //         User.update({userId:userId},{
    //             $set: {cartList:doc.cartList}
    //         },(err)=>{
    //             if(err){
    //                 res.json({
    //                     status:'1',
    //                     msg:err.message,
    //                     result:''
    //                 })
    //             }else{
    //                 res.json({
    //                     status:'0',
    //                     msg:'',
    //                     result:doc.cartList
    //                 })
    //             }
    //         })
    //     }
        
    // })
  
   //直接更新子文檔
    User.update({userId:userId,"cartList.productId":pdId},{
        $set: {"cartList.$.productNum":num},
        $set: {"cartList.$.checked":checked}
    },(err)=>{//更新子文檔
        if(err){
            res.json({
                status:'1',
                msg:err.message,
                result:''
            })
        }else{
            res.json({
                status:'0',
                msg:'更新成功',
                result:''
            })
        }
    })   
})

4、購物車全選

點擊全選按鈕時,將是否選中的狀態通過flag傳給后端,如果后端更新成功,前端就將遍歷商品將checked設置為相應狀態。在后端,首先接收是否需要全選isAll,然后通過userId找到用戶的cartLIst,遍歷列表,將整個cartList的checked設置為相應的狀態。改完之后保存數據

data(){
            return{
              cartList:[],
              mdDel:false,
              productId:''
            }
        },
        mounted(){
          this.init();
        },
        methods:{
          init(){
            axios.get('/users/cartList').then((response)=>{
              let res=response.data;
              this.cartList=res.result;
            })
          },
         delPrd(id){
            this.mdDel=true;
            this.productId=id;     
          },
          prdDel(){
            axios.post('/users/delprd',{
              productId:this.productId
            }).then((response)=>{
              let res=response.data;
              if(res.status=='0'){
                this.mdDel=false;
                this.init();
              }
            })
          },
         editCart(item,flag){
            let oldNum=item.productNum;
            if(flag=='add'){
              item.productNum++;
            }else if(flag=='minus'){
              if(item.productNum<=1){
                return;
              }else{
                item.productNum--;
              }   
            }else{
              item.checked*=-1;
            }
            axios.post('/users/changeNum',{
              pdId:item.productId,
              num:item.productNum,
              checked:item.checked
            }).then((response)=>{
              let res=response.data;
              if(res.status!='0'){
                item.productNum=oldNum;
                alert('更改商品數量失敗')
              }
            })
          },
         selectAll(){
            // this.isAll=!this.isAll;//在computed實時計算了不能在這再賦值了,
            var flag=!this.isAll
            axios.post('/users/selectAll',{
              isAll:flag
            }).then((response)=>{
              if(response.data.status=='0'){
                this.cartList.forEach((item)=>{
                    if(flag){
                        item.checked=1;
                     }else{
                        item.checked=-1;
                     }  
                })
              }
            })       
          },
       },
        components:{
            NavHeader,
            NavFooter,
            NavBread,
            Modal
        }
    }

后端代碼:

router.post('/selectAll',(req,res,next)=>{
    let userId=req.cookies.userId;
    let isAll=req.body.isAll;
    User.findOne({userId:userId},(err,doc)=>{
        if(err){
            res.json({
                status:'1',
                msg:err.message,
                result:''
            })
        }else{
            doc.cartList.forEach((item)=>{
                if(isAll){
                    item.checked=1;
                }else{
                    item.checked=-1;
                }
                
            })
            doc.save((err1,doc1)=>{
                if(err1){
                    res.json({
                        status:'1',
                        msg:err.message,
                        result:''
                    })
                }else{
                    res.json({
                        status:'0',
                        msg:'',
                        result:'suc'
                    })
                }
            })
        }
    })
})

5、商品實時計算功能

computed中添加的實際上是data,返回一個實時變化的值,這對計算商品總價錢很方便,首先將isAll變量用動態的商品屬性checked的個數來計算,如果checked的商品等于cartList里的商品長度,isAll就是全選的狀態,如果不是就不是全選的狀態。其次,總價錢也實時計算,遍歷整個列表,計算商品的個數*價錢。

 computed:{//實時計算,相當于watch方法
          isAll(){
            let count=0;
            this.cartList.forEach((item)=>{
              if(item.checked==1){
                count++;
              }
            })
            return count===this.cartList.length;
          },
          totalMoney(){
            let totalMoney=0;
            this.cartList.forEach((item)=>{
              if(item.checked==1){
                totalMoney+=parseFloat(item.salePrice)*parseInt(item.productNum);
              }
            })
            return totalMoney;
          }
      },

6、filter格式化

在組件內部定義filters,寫過濾方法,在頁面中需要格式化的地方調用

{{ totalMoney | currency('$')}}
import {currency} from './../util/currency'
filters:{
          currency:currency
        },

在main.js中定義全局過濾器。

import {currency} from './util/currency'
Vue.filter("currency",currency);

currency代碼:

const digitsRE = /(\d{3})(?=\d)/g

export function currency (value, currency, decimals) {
  value = parseFloat(value)
  if (!isFinite(value) || (!value && value !== 0)) return ''
  currency = currency != null ? currency : '$'
  decimals = decimals != null ? decimals : 2
  var stringified = Math.abs(value).toFixed(decimals)
  var _int = decimals
    ? stringified.slice(0, -1 - decimals)
    : stringified
  var i = _int.length % 3
  var head = i > 0
    ? (_int.slice(0, i) + (_int.length > 3 ? ',' : ''))
    : ''
  var _float = decimals
    ? stringified.slice(-1 - decimals)
    : ''
  var sign = value < 0 ? '-' : ''
  return sign + currency + head +
    _int.slice(i).replace(digitsRE, '$1,') +
    _float
}

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,797評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,179評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,628評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,642評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,444評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,948評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,040評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,185評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,717評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,794評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,418評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,414評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,750評論 2 370

推薦閱讀更多精彩內容