vue2-elm學習記錄(Day10)

實現三:商品和評價切換(續)

food-detail-list的內容:
image.pngvue

...
<section class="menu_detail_list" v-for="(foods,foodindex) in item.foods" :key="foodindex">
    <!--點擊跳轉到食物詳情頁面,須要傳入的參數:
        image_path:圖片路徑,
        description:食物描述
        month_sales:月銷量
        name:食物名字
        ratting:評分,
        rating_count:銷售量,
        satisfy_rate:滿意度,
        foods:食物,
        shopId:店鋪id-->
        <router-link class="menu_detail_link" :to="{
        path:'shop/foodDetail',query:{image_path:foods.image_path,
        description:foods.description,
        month_sales:foods.month_sales,
        name:foods.name,
        rating:foods.rating,
        rating_count:foods.rating_count,
        satisfy_rate:foods.satisfy.rate,
        foods.shopId}
        }" tag="div">
            <!--圖片 s-->
            <section class="menu_food_img">
                <img :src="imgBaseUrl+foods.image_path">
            </section>
            <!--圖片 e-->
            <!--描述信息 s-->
            <section class="menu_food_description">
                <h3 class="food_description_head">
                    <!--標題-->
                    <strong class="description_foodname">
                        {{foods.name}}
                    </strong>
                    <!--是不是新品 s-->
                    <ul class="attributes_ul" v-if="foods.attributes.length">
                        <li v-if="attribute" v-for="(attribute,foodIndex) in foods.attributes"
                         :key="foodindex" :style="{color:'#'+attribute.icon_color,
                          borderColor:'#'+attribute.icon_color}"
                          :class="{attribute_new:attribute.icon_name=='新'}">
                            <!--attribute.icon_name=='新'的時候,顯示name值,並未其添加樣式-->
                            <p :style="{color:attribute.icon_name=='新'?'#fff':'#'+attribute.icon_color}">
                               {{attribute.icon_name=='新'?'新品':attribute.icon_name}}
                            </p>
                        </li>
                    </ul>
                    <!--是不是新品 e-->
                </h3>
                <!--描述信息-->
                <p class="food_description_content">
                    {{foods.description}}
                </p>
                <!--銷量和滿意度-->
                <p class="food_description_sale_rating">
                    <span>月售{{foods.month_sales}}份</span>
                    <span>好評率{{foods.satisfy_rate}}%</span>
                </p>
                <!--foods.activity是已售的意思嗎-->
                <p v-if="foods.activity" class="food_activity">
                    <span :style="{color:'#'+foods.activity.image_text_color,
                     borderColor:'#'+foods.activity.icon_color}">
                        {{foods.activity.image_text}}
                    </span>
                </p>
            </section>
            <!--描述信息 e-->
        </router-link>
        <!--價格 s-->
        <footer class="menu_detail_footer">
            <section class="food_price">
                <span>¥</span>
                <span>{{foods.specfoods[0].price}}</span>
                <span v-if="foods.specifications.length"></span>
            </section>
        </footer>
        <!--價格 e-->
</section>
...

說明:
foods的數據結構以下:
image.pnggit

功能(1):增長點擊右側"..."顯示說明信息

image.png

...
<header class="menu_detail_header">
    ...
    <!--點擊部分-->
    <span class="menu_detail_header_right" @click="showTitleDetail(index)"></span>
    <!--點擊的時候控制TitleDetailIndex值進而控制列表的展現和隱藏-->
    <p class="description_tip" v-if="index==TitleDetailIndex">
        <span>{{item.name}}</span>
        {{item.description}}
    </p>
</header>
...

JS部分:github

export default{
        data(){
            return{
            ...
            //點擊展現列表頭部詳情
            TitleDetailIndex:null
            
            }
        },
        //說明信息的隱藏和顯示
        showTitleDetail(index){
            if(this.TitleDetailIndex==index){
                this.TitleDetailIndex=null;
            }
            else{
                this.TitleDetailIndex=index;
            }
        
        }
        
    }
功能(2):加購

若標識規格的參數specifications沒有長度的時候顯示+號,若標識規格的參數specifications有長度時顯示"規格"。
image.png
須要用到Vuex。vuex

知識點:

(1)vuex的狀態存儲是響應式的,因此從store中讀取狀態最簡單的方法就是經過computed計算屬性。
每當state中的狀態發生變化時,就會從新計算獲取計算屬性從而映射到View。
(2)當一個組件有多個狀態的時候,會形成計算屬性重複和代碼冗餘。爲了解決這個問題,咱們可使用
mapState輔助函數幫助咱們生成計算屬性:
(3)Mutations修改狀態的值,vue視圖是由數據驅動的,也就是說state裏面的數據是動態變化的,而改變的
惟一方法就是mutation,通俗的理解,mutations裏面裝着一些改變數據方法的集合。每一個 mutation 都有一個字符串的事件類型 (type) 和 一個回調函數 (handler)。事件類型就是經過$store.commit()提交的事件。回調
函數就是咱們實際進行狀態更改的地方,它做爲store中的mutations對象的一個屬性而存在。
(4)在組件中提交Mutations
首先引入mapMutations
import {mapState,mapMutations} from 'vuex'
添加methods屬性,並加入mapMutations
eg:數組

...
methods:{
    //若是組件中事件的名稱和mutations中方法的名稱相同,能夠傳一個字符串數組
    ...mapMutations([
        'add'//映射this.add()爲this.$store.commit('add')
    ])
}

(5)Actions:是異步修改狀態。actions和mutations是相似的,不一樣之處在於:數據結構

  • Action提交的是Mutation,不可以直接修改state中的狀態,而Mutations是能夠直接修改state中狀態的;
  • Action是支持異步操做的,而Mutations只能是同步操做。
實現:

mutation-types.js中定義:異步

//加入購物車
export const ADD_CART = 'ADD_CART'
//移除購物車
export const REDUCE_CART = 'REDUCE_CART'
//清空購物車
export const CLEAR_CART='CLEAR_CART'
//保存商鋪ID
export const SAVE_SHOPID = 'SAVE_SHOPID'

mutations.js中定義方法:svg

//引入常量
import {ADD_CART,REDUCE_CART,CLEAR_CART,SAVE_SHOPID} from './mutation-types.js'
import {setStore,getStore} from '../config/mUtils';
export default{
   //加入購物車
   [ADD_CART](state,{
        //店鋪id
        shopid,
        //分類id
        categpry_id,
        item_id,
        food_id,
        name,
        price,
        //規格
        specs,
        //打包費
        packing_fee,
        //身份證
        sku_id,
        //庫存
        stock
   }){
      let cart=state.cartList;
      let shop=cart[shopid]= (cart[shopid] || {});
      let category=shop[category_id]= (shop[category_id] || {});
      let item=category[item_id] = (category[item_id] || {});
      if(item[food_id]){
        item[food_id]['num']++;
      }
      else{
        item[food_id]={
            "num":1,
            ///食物id
            "id":food_id,
            //名字
            "name":name,
            //價格
            "price":price,
             //規格
            "specs":specs,
            //打包費
            "packing_fee":packing_fee,
            //身份證
            "sku_id":sku_id,
            //庫存
            "stock":stock
        };
      }
      state.cartList={...cart};
      //存入localStorage
      setStore('buyCart',state.cartList);
   },
   //移出購物車
   [REDUCE_CART](state,{
    shopid,
    category_id,
    item_id,
    food_id,
    name,
    price,
    specs
   }){
        let cart=state.cartList;
        let shop=(cart[shopid] || {});
        let category = (shop[category_id] || {});
        let item = (category[item_id] || {});
        if(item&&item[food_id]){
            if(item[food_id]['num']>0){
               item[food_id]['num']--;
               state.cartList={..cart};
               //存入localStorage
               setStore('buyCart',state.cartList);
            }
            else{
                //商品數量爲0,則清空當前商品的信息
                item[food_id]=null;
            }
        }
   },
   //清空當前商品的購物車信息
   [CLEAR_CART](state,shopid){
    state.cartList[shopid]=null;
    state.cartList={...state.cartList};
    setStore('buyCart',state.cartList);
   },
   //保存商鋪id
   [SAVE_SHOPID](state,shopid){
    state.shopid=shopid;
   }
}

store文件夾下的index.js:函數

const state={
    ...
    //加入購物車的商品列表
    cartList:{},
    //商鋪id
    shopid:null,
    //購物車id
    cartId:null
}
export default new Vuex.Store({
    state,
    getters,
    actions,
    mutations
})

buyCart.vue:佈局

<section class="cart_module">
    <!--顯示+/-號的狀況 s -->
    <section class="cart_button" v-if="!foods.specifications.length">
        <!--減號(有數字的時候顯示)-->
        <transition name="showReduce">
            <span v-if="foodNum">
                <!--點擊減號執行removeOutCart,removeOutCart的對應方法
                    在mutations.js中
                    須要傳入的參數:
                    category_id(類別id)
                    item_id(項目id)
                    specfoods(特殊食品)的:
                    food_id(食品id),
                    name(食品的名字),
                    price(食品的價格),
                    packing_fee(食品包裝費)
                    sku_id(庫存id)
                    stock(存貨)
                 -->
                <svg  @click="removeOutCart(
                      foods.category_id,
                      foods.item_id,
                      foods.specfoods[0].food_id,
                      foods.specfoods[0].name,
                      foods.specfoods[0].price,
                      '',
                      foods.specfoods[0].packing_fee,
                      foods.specfoods[0].sku_id,
                      foods.specfoods[0].stock)">
                    <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#cart-minus" />
                </svg>
            </span>
        </transition>
        <!--數字 foodNum來自於mutations.js中-->
        <transition name="fade">
            <span class="cart_num" v-if="foodNum">{{foodNum}}</span>
        </transition>
        <!--加號:點擊+號執行addToCart方法,傳入參數同上-->
        <svg class="add_icon"  @click="addToCart(
          foods.category_id,
          foods.item_id,
          foods.specfoods[0].food_id,
          foods.specfoods[0].name,
          foods.specfoods[0].price,
          '',
          foods.specfoods[0].packing_fee,
          foods.specfoods[0].sku_id,
          foods.specfoods[0].stock,
          $event)">
            <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#cart-add" />
        </svg>
    </section>
    <!--顯示+/-號的狀況 e-->
    <!--顯示規格的狀況  s-->
    <section class="choose_specification" v-else>
        <section class="choose_icon_container">
            <transition name="showReduce">
                <!--點擊的時候執行showReduceTip方法-->
                <svg class="specs_reduce_icon" v-if="foodNum" @click="showReduceTip">
                   <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#cart-minus" />
                </svg>
            </transition>
            <transition name="fade">
                <!--顯示的數字,有點看不懂-->
                <span class="cart_num" v-if="foodNum">{{foodNum}}</span>
            </transition>
            <!--點擊的時候顯示規則選擇框-->
            <span class="show_chooselist" @click="showChooseList(foods)">選規格</span>
        </section>
    </section>
    <!--顯示規格的狀況  e-->
</section>

JS部分

export default{
        data(){
            return{
                //控制下落的小圓點的顯示和隱藏
                showMoveDot:[]
            }
        },
        mounted(){},
        computed:{
            //獲取cartList,將this.cartList映射爲this.$store.commit('add_cart')
            ...mapState(["cartList"]),
            //監聽cartList變化,更新當前商鋪的購物車信息shopCart,同時返回一個新的對象
            shopCart:function(){
                return Object.assign({},this.cartList[this.shopId]);
            },
            //添加的食品的個數
            foodNum:function(){
                 //類型id
                 let category_id = this.foods.category_id;
                 //項目id
                 let item_id = this.foods.item_id;
                 //這個地方判斷的做用沒搞懂,若它們都有值能表明什麼呢
                 if(this.shopCart &&
        this.shopCart[category_id] &&
        this.shopCart[category_id][item_id]){
                      let num=0;
                      Object.values(this.shopCart[category_id][item_id]).forEach(
                        (item,index)=>{
                            num+item.num
                        }
                      );
                      return num
                        
                        
                  }
                  else{
                    return 0;
                  }
            }
            
        },
        props: ["foods", "shopId"],
        methods:{
          ...mapMutations(["ADD_CART", "REDUCE_CART"]),
          //移出購物車
          removeOutCart(category_id,
               item_id,
               food_id,
                name,
                price,
                specs,
                packing_fee,
                sku_id,
                stock){
                if(this.foodNum>0){
                    //調用REDUCE_CART方法
                    this.REDUCE_CART({
                      shopid: this.shopId,
                      category_id,
                      item_id,
                      food_id,
                      name,
                      price,
                      specs,
                      packing_fee,
                      sku_id,
                      stock
                    });
                 
                 }
          
            },
            //加入購物車
            addToCart(
            category_id,
            item_id,
            food_id,
            name,
            price,
            specs,
            packing_fee,
            sku_id,
            stock,
            event){
               this.ADD_CART({
                    shopid: this.shopId,
                    category_id,
                    item_id,
                    food_id,
                    name,
                    price,
                    specs,
                    packing_fee,
                    sku_id,
                    stock
               }); 
               let elLeft=event.target.getBoundingClientRect().left;
               let elBottom=event.target.getBoundingClientRect().bottom;
               this.showMoveDot.push(true);
               this.$emit("showMoveDot",this.showMoveDot,elLeft,elBottom);
            },
            //顯示規格列表
            showChooseList(foodScroll){
                this.$emit("showChooseList",foodScroll);
            },
            //點擊多規格商品的減按鈕,彈出提示
            showReduceTip(){
                this.$emit("showReduceTip");
            }
        }
    }

shop.vue中引入buyCart.vue:

...
<section class="menu_right" ref="menuFoodList">
    <ul>
        <li v-for="(item,index) in menuList" :key="index">
            ...
            <footer class="menu_detail_footer">
                ...
                <!--showChooseList顯示規格列表
                    showReduceTip:點擊多規格商品的減按鈕,彈出提示
                    showMoveDot:
                    傳遞過來的參數:this.$emit("showMoveDot",this.showMoveDot,elLeft,elBottom)
                -->
                <buy-cart :shopid="shopId" :foods="foods"
                      @moveInCart="listenInCart"
                      @showChooseList="showChooseList"
                      @showReduceTip="showReduceTip"
                      @showMoveDot="showMoveDotFun"
                  >
                    
                </buy-cart>
            </footer>
        </li>
    </ul>
</section>

到此爲止,規格和加號的佈局已完整。功能實現收其餘部分的影響,暫時不作說明。
參照項目地址:地址

相關文章
相關標籤/搜索