Vue(小案例_vue+axios仿手機app)_購物車(二模擬淘寶購物車頁面,點擊加減做出相應變化)


一、前言                                                                             

在上篇購物車中,如果用戶刷新了當前的頁面,底部導航中的數據又會恢復為原來的:

                                                          1、解決刷新,購物車上數值不變

                                                          2、在購物車點擊加減按鈕,數值做出對應變化

 

 

二、主要內容                                                                      

1、實現效果:點擊購物車的時候可以查看到購物車的商品信息

 

 

 

2、解決刷新,購物車上數值不變

  (1)新建一個Cart.vue展示購物信息,並將路由添加到index.js中

  (2)購物車里面涉及到:存儲商品信息,獲取商品信息,保存商品信息,這里將這些方法單獨封裝到一個.js文件中(本來需要在后台操作)

let obj={}; //定義一個對象,存儲商品信息

//這里需要存儲數據
//{商品的id, 商品的數量}

//保存商品
obj.saveGoods = function(goodsList){
    window.localStorage.setItem('goodsList',JSON.stringify(goodsList))
}


//獲取商品的值
obj.getGoodsList = function(){
    return JSON.parse(window.localStorage.getItem('goodsList'|| '{}'))//如果stroge中沒有值,返回一個空對象
}

//增加商品
obj.add = function(goods){
    let goodsList = this.getGoodsList()//獲取到storage里面的對象
    if(goodsList[goods.id]){

        //goods.id是商品的數量,對應有值的話就追加
        goodsList[goods.id] = goodsList[goods.id] + goods.num;  
    }else{
        goodsList[goods.id]=goods.num;
    }

    //傳進來之后還需要保存
    this.saveGoods(goodsList);
} 

//獲取購物車的總數量
obj.getTotalCount = function(){
    let goodsList = this.getGoodsList();
    let values = Object.values(goodsList);//Object.values返回的是一個數組,里面對應着每一個key的value
    let sum = 0;
    values.forEach(val => sum = sum +val);
    return sum;

}

export default obj;

  (2)封裝好了方法就要在商品詳情頁面使用(類似於我們在淘寶上買東西,當你在商品詳情頁面點擊加入購物車之后,購物車里面會有對應的商品)

 name:'GoodsDetail',
        data(){
            return{
                url:`getthumImages/${this.$route.params.id}`,
                goodsInfo:{},//當前購物車的信息,里面有id
                pickNum:1 ,
                isExist:false //讓小球默認是隱藏的狀態, 
            }
        },
        methods:{
            afterEnter(){
                this.isExist=false; //顯示出來之后執行這個,又將小球隱藏
                this.$bus.$emit('sendPickNum',this.pickNum);

                //當觸發了上面的事件之后,
                GoodsTool.add({
                    id:this.goodsInfo.id,
                    num:this.pickNum
                })
            },
            //點擊加入購物車執行這個方法,然后讓小球顯示出來
            ballHandler(){
                this.isExist=true;
              //  this.$bus.$emit('sendPickNum',this.pickNum); //將當前的pickNum傳過去,但是這個不能加在這里,否者一點擊“加入購物車就傳
            },
            

  (3)當你一刷新,stroge里面的數據清空,下面的購物車上面的數值又變成0了,所以在下面的底部導航里,讓他一開始就獲取到當前這個總數

created(){
    //當你的組件一創建好了后就掛載這個bus公交車,$on這個事件監聽
    this.$bus.$on(`sendPickNum`, (data)=>{
      this.pickNum=this.pickNum + data; /
    }),

    this.pickNum=GoodsTool.getTotalCount();//直接將這Goods.vue里面傳來的數據賦值,
  }

  (4)通過以上思路,就能保證刷新頁面時,購物車中的數據不發生改變

 

3、點擊底部導航“購物車”,將上面加進的東西和數量展示在頁面中,(在購物車點擊加減按鈕,數值做出對應變化)

  (1)首先發送請求,這里發送請求的時候,需要之后再購物詳情頁面加入的商品的id, 然后根據對應的id拿到對應的請求數據

  (2)拿到購物詳情里面的id

let goodsList = GoodsTool.getGoodsList();//["88":5,"99":4] 第一個數商品id 第二個是商品數量
            let ids = Object.key(goodsList).join(',');//Object.key()獲取key值 [88,99]

  (3)拿到上面的id之后就可以發請求

created(){
            let goodsList = GoodsTool.getGoodsList();//{"88":5,"99":4} 第一個數商品id 第二個是商品數量
            let ids = Object.key(goodsList).join(',');//Object.key()獲取key值 [88,99]
            if(ids){
                this.$axios.get(`goods/getshopcarlist${ids}`)
                .then(res=>{
                    this.shopCart=res.data.message;
                 
                         }   
                })
         }

  (4)但是這里的后端數據庫里並沒有保存加入購物車的數量(如果有可以直接從后端獲取),這里手動添加

created(){
            let goodsList = GoodsTool.getGoodsList();//{"88":5,"99":4} 第一個數商品id 第二個是商品數量
            let ids = Object.key(goodsList).join(',');//Object.key()獲取key值 [88,99]
            if(ids){
                this.$axios.get(`goods/getshopcarlist${ids}`)
                .then(res=>{

                    this.shopCart=res.data.message;//返回的是一個數組
                  //給數組元素添加屬性
                  for(var i=0; i<this.shopCart.length;i++){
                      let shop=this.shopCart[i];//獲取到當前的對象
                      let num = goodsList[shop.id];//根據當前對象的id查找到對應的購物車數量

                        shop.num = num;//給每個對象添加一個num屬性,並在視圖上渲染,但是會發現視圖上的值並沒有改變

                      }

                  }
                })
            }

  (5)在購物車列表做加減操作,並且將當前的對象傳進去

 <li class="p-list" v-for="(shop, index) in shopCart">
                    <mt-switch></mt-switch>
                    <img src="">
                    <div class="pay-calc">
                        <p>{{shop.title}}</p>
                        <div class="calc">
                            <span>¥777</span>
                            <span @click="substract(shop)">-</span>
                            <span>{{shop.num}}</span>
                            <span @click="addNum(shop)">+</span>
                            <a href="javascript:;">刪除</a>
                        </div>
                    </div>
                </li>

 

methods:{
            addNum(shop){//每次點擊都接受到當前的對象
                shop.num++; //這里的值雖然加上了,但是,數據並沒有響應上去,是因為created是一開始就加載的,后來點擊修改了num的值,但是沒有 響應視圖
                console.log(shop)
            },
            substract(shop){
                if(shop.num==1){
                    return;
                }

                shop.num--;

            }

        },

  (6)做完第五步,在測試的時候,發現控制台中打印出來的對象中num改變,但是視圖上並沒有改變

    原因:vue 中存在一種機制會將shopCart(也就是你請求的數據進行監視)屬性進行監視,完成響應式(因為后面的num是我們自己加進去的,沒有掛載到數據屬性里面,vue就會對這個屬性進行監視,監視到數據不是完全掛載到數據屬性上的,就無法完成響應操作)

              在vue中的源碼中會生成 Object.defineProperty(this, 'shopCart', {   set:function(){   //判斷shopCart元素是否有屬性  })

    解決方法:如果數據不完整掛載的情況在要添加屬性,就需要手動通知vue完成響應式,==》雙向數據綁定

created(){
            let goodsList = GoodsTool.getGoodsList();//{"88":5,"99":4} 第一個數商品id 第二個是商品數量
            let ids = Object.key(goodsList).join(',');//Object.key()獲取key值 [88,99]
            if(ids){
                this.$axios.get(`goods/getshopcarlist${ids}`)
                .then(res=>{

                    this.shopCart=res.data.message;//返回的是一個數組
                  //給數組元素添加屬性
                  for(var i=0; i<this.shopCart.length;i++){
                      let shop=this.shopCart[i];//獲取到當前的對象
                      let num = goodsList[shop.id];//根據當前對象的id查找到對應的購物車數量

                      if(num){
                          shop.num = num;

                          this.$set(shop, 'num', num);//自己給這個數據進行雙向數據綁定
                          this.$set(shop,'isSelected',true);
                      }
                  }
                })
            }

 

 

 

三、總結                                                                             

踩坑一:自己收動添加的屬性,需要用$set()給這個屬性綁定

踩坑二:vue 中存在一種機制會將shopCart(也就是你請求的數據進行監視)屬性進行監視,完成響應式(因為后面的num是我們自己加進去的,沒有掛載到數據屬性里面,vue就會對這個屬性進行監視,監視到數據不是完全掛載到數據屬性上的,就無法完成響應操作)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM