food-detail-list的內容:vue
... <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的數據結構以下:git
... <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; } } }
若標識規格的參數specifications沒有長度的時候顯示+號,若標識規格的參數specifications有長度時顯示"規格"。
須要用到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是相似的,不一樣之處在於:數據結構
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>
到此爲止,規格和加號的佈局已完整。功能實現收其餘部分的影響,暫時不作說明。
參照項目地址:地址