<template> <!--vue的render渲染須要有一個root的根dom層,因此建立一個單獨的div來包裹--> <div> <!--這是shopcart的主代碼--> <div class="shopcart"> <!--用toggleList點擊顯示隱藏購物車列表--> <div class="content" @click="toggleList"> <div class="content-left"> <div class="logo-wrapper"> <div class="logo" :class="{'highlight':totalCount>0}"> <i class="icon-shopping_cart" :class="{'highlight':totalCount>0}"></i> </div> <div class="num" v-show="totalCount>0">{{totalCount}}</div> </div> <div class="price" :class="{'highlight':totalPrice>0}">¥{{totalPrice}}</div> <div class="desc">另需配送費¥{{deliveryPrice}}元</div> </div> <!--支付--> <div class="content-right" @click.stop.prevent="pay"> <!--這裏class綁定的是一個payClass計算屬性--> <div class="pay" :class="payClass"> {{payDesc}} </div> </div> </div> <!--省略了ball-container是動畫小球的部分--> <!--shopcart的列表詳情部分--> <transition name="fold"> <div class="shopcart-list" v-show="listShow"> <div class="list-header"> <h1 class="title">購物車</h1> <span class="empty" @click="empty">清空</span> </div> <div class="list-content" ref="listContent"> <ul> <li class="food" v-for="food in selectFoods"> <span class="name">{{food.name}}</span> <div class="price"> <span>¥{{food.price * food.count}}</span> </div> <!--列表裏面能夠進行操做,因此會複用一個cartcontrol的組件--> <div class="cartcontrol-wrapper"> <cartcontrol @add="addFood" :food="food"></cartcontrol> </div> </li> </ul> </div> </div> </transition> </div> <!--打開shopcart列表的時候背景須要虛化而且動畫--> <transition name="fade"> <div class="list-mask" @click="hideList" v-show="listShow"></div> </transition> </div> </template>
import BScroll from 'better-scroll'; import cartcontrol from '../../components/cartcontrol/cartcontrol'; export default{ props: { selectFoods: { type: Array, default(){ //data必須是一個函數,這是默認值data的寫法 return [ {} ]; } }, deliveryPrice: { type: Number, default: 0 }, minPrice: { type: Number, default: 0 } }, data(){ return { fold: true //經過這個變量來控制隱藏和顯示購物車列表,true表明隱藏,摺疊起來 } }, computed: { totalPrice(){ //計算總價 let total = 0; this.selectFoods.forEach((food) => { total += food.price * food.count; //這個count就是在goods組件裏面添加的 }) return total; }, totalCount(){ //計算總數量 let count = 0; this.selectFoods.forEach((food) => { count += food.count; }) return count; }, payDesc(){ //只是簡單的作一些支付顯示的計算 if (this.totalPrice === 0) { return `¥${this.minPrice}元起送`; } else if (this.totalPrice < this.minPrice) { let diff = this.minPrice - this.totalPrice; return `還差¥${diff}元配送`; } else { return `去結算`; } }, payClass(){ if (this.totalPrice < this.minPrice) { return 'not-enough'; } else { return 'enough'; } }, listShow(){ //自動計算購物車列表是否顯示和隱藏 if (!this.totalCount) { //自動判斷商品數量爲空 this.fold = true; //直接隱藏 return false; } let show = !this.fold; //當flod爲false的時候顯示購物車列表 if (show) { this.$nextTick(() => { //異步執行滾動列表初始化 if (!this.scroll) { this.scroll = new BScroll(this.$refs.listContent, { click: true }); } else { this.scroll.refresh(); } }); } return show; } }, methods: { toggleList(){ if (!this.totalCount) { return; } this.fold = !this.fold; }, empty() { //經過清空數據屬性來控制購物車清空 this.selectFoods.forEach((food) => { food.count = 0; }); }, hideList() { this.fold = true; }, pay() { if (this.totalPrice < this.minPrice) { return; } window.alert(`支付${this.totalPrice}元`); } }, components: { cartcontrol } }
購物車列表的顯示和隱藏(摺疊)是經過數據fold來決定的,他是經過計算屬性listshow來實現的,這樣達到了不用操做dom就能夠改變dom行爲的效果,vue的數據驅動設計.css
清空按鈕也是這樣實現的,經過批量設置count屬性來實現html
拋物線小球部分參考:關於購物車添加按鈕的動畫vue
由於打開shopcart詳情頁會出現兩個內容:segmentfault
shopcart-list部分參考:八.shopcart-list購物車詳情頁app
cartcontrol部分參考:cartcontrol.vue購物車操做按鈕dom
又由於這個cartcontrol是有幾個地方都須要用到的,因此將其組件化處理異步
@import "../../common/stylus/mixin.styl" .shopcart position: fixed //這是固定在頁面底部的購物車欄目 left: 0 bottom: 0 z-index: 50 width: 100% height: 48px .content display: flex //flex佈局 background: #141d27 font-size: 0 .content-left flex: 1 .logo-wrapper display: inline-block position: relative top: -10px //由於要凸出購物車欄目一點點,設計須要 margin: 0 12px padding: 6px width: 56px //由於使用了border-box的關係,能夠直接寫設計的尺寸 height: 56px box-sizing: border-box //border-box能夠省去計算border和內邊距 vertical-align: top border-radius: 50% background: #141d27 .logo width: 100% height: 100% border-radius: 50% text-align: center background: #2b343c &.highlight background: rgb(0, 160, 220) .icon-shopping_cart line-height: 44px font-size: 24px color: #80858a &.highlight color: #ffffff .num position: absolute top: 0 right: 0 width: 24px height: 16px line-height: 16px text-align: center border-radius: 16px font-size: 9px color: #ffffff background: rgb(240, 20, 20) box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.4) .price display: inline-block vertical-align: top margin-top: 12px line-height: 24px padding-right: 12px box-sizing: border-box border-right: 1px solid rgba(255, 255, 255, 0.1) font-size: 16px font-weight: 700 color: rgba(255, 255, 255, 0.4) &.highlight color: #ffffff .desc display: inline-block vertical-align: top margin: 12px 0 0 12px line-height: 24px color: rgba(255, 255, 255, 0.4) font-size: 10px .content-right flex: 0 0 105px //flex佈局固定右邊空間 width: 105px .pay height: 48px line-height: 48px text-align: center font-size: 12px color: rgba(255, 255, 255, 0.4) font-weight: 700 &.not-enough background: #2b333b &.enough background: #00b43c color: #ffffff //省略了小球動畫的css
這裏主要注意border-box的使用,舉例logo-wrapperide
寬高都是56px,而且須要實現內邊距是6px函數
不用border-box的話,就要計算圖片的區域是多大,而後加上6px內邊距等於56px組件化
用了border-box的話,就不須要計算圖片區域了,直接寫56px,即便加上6px內邊距也不撐大56px的區域,只會自動縮小內部圖片區域的區域,實際狀況就是外框區域56px,內邊距6px,圖片自動縮小到44px(6+44+6等於56)