1.上一章--watch監聽子路由
2.蒼渡大神源碼--項目源碼地址
3.數據接口--API接口
4.UI框架--Mint UI
5.下一章--購物車的詳細信息展現與刪除css
1.先看一下目前的UI圖
vue
要實現的UI圖
node
2.footdiv
代碼修改以下git
<transition name="left"> <div v-if="footdiv" class="foot on"> <div class="footleft"> <div class="footlogo"> <icon name="footcar" class="footicon"></icon> <div class="rednum">15</div> </div> <div class="footmain"> <div v-if="false" class="">未選購商品</div> <div class="ih30 fs1-2">¥ 3205</div> <div class="ih20">配送費 ¥5</div> </div> </div> <div class="footright"> <span >¥20起送</span> <span v-if="false">還差¥15起送</span> <span v-if="false">去結算</span> </div> </div> </transition>
css以下github
.foot{ height:50px; line-height:50px; background-color:#594C46; display:flex; position:fixed; bottom:0px; left:0px; width:100%; } .foot.on .footicon{ color:#fff; } .foot.on .footmain{ color:#fff; } .foot.on .footlogo{ background-color:#3190E8; } .foot.on .footright{ color:#fff; } .footleft{ flex:2; display:flex; } .footright{ flex:1; text-align:center; color:#B7B7B7; background-color:#61686A; } .footright.on{ background-color:#4CD964; color:white; } .footlogo{ text-align:center; width:50px; height:50px; border-radius:50%; background-color:#515151; margin:0px 10px; border:3px solid #444446; transform:translatey(-15px) } .footicon{ color:#8a8a8a; width:40px; height:40px; margin-top:7px; } .footmain{ height:50px; color:#ADADAD; font-size:0.8rem; } .rednum{ position: absolute; top:-3px; right:-5px; border-radius:50%; background-color:red; color:white; height:18px; width:18px; text-aligin:center; line-height:18px; font-size:12px; }
我把全部可能出現的元素所有寫出來了,用v-if來判斷顯示哪一個,到時候購物車有東西了,直接給footdiv
加一個on
class就行。web
3.點擊添加
注意,首先咱們要把佈局修改一下
segmentfault
之前綠色的div在紅色的div內,而紅色div有一個點擊跳轉的效果,因此點擊綠色div也會跳轉。這在js中解決很是簡單,可是在vue中怎麼解決呢?我上網查了查沒找到結果(哪位老鐵知道怎麼解決感謝指出)。。。最後是用佈局解決的。
解決後紅色div與綠色div是兄弟並非父子,將綠色div定位到紅色div上便可。框架
4.數據類型
我們把數據存到localStorage
裏,鍵名爲mycar
,鍵值結構爲dom
[{"shop":第一個商品的相關信息,"num":第一個商品的個數},{"shop":第二個商品的相關信息,"num":第二個商品的個數}]
(注意:localStorage
只接收字符串,因此我們存取都要先轉化再使用)
(注意:下面點擊事件的參數e爲API返回的一個完整的食品對象,狠狠的點擊這裏查看API,截圖以下)
函數
點擊事件以下
addcar:function(e){ var that=this; if(localStorage.getItem("mycar")){ var mycar=JSON.parse(localStorage.getItem("mycar")); var addok=true; //數據是否添加 for(var i =0;i<mycar.length;i++){ if(mycar[i].shop.item_id==e.item_id&&mycar[i].shop.category_id==e.category_id&&mycar[i].shop.restaurant_id==e.restaurant_id){ mycar[i].num=mycar[i].num+1; addok=false; break; } } if(addok){ mycar.push({"shop":e,"num":1}); } that.mycar=mycar; localStorage.setItem("mycar",JSON.stringify(mycar)); }else{ var mycar=[{"shop":e,"num":1}]; that.mycar=mycar; localStorage.setItem("mycar",JSON.stringify(mycar)); } }
(注意:別忘了在data中設置變量mycar
來存放購物車信息)
在footdiv
中監聽mycar
來控制on
class是否添加和右上角的紅色數字是否顯示。
<transition name="left"> <div v-if="footdiv" class="foot" :class="{on:mycar.length>=1}"> <div class="footleft"> <div class="footlogo"> <icon name="footcar" class="footicon"></icon> <div v-if="mycar" class="rednum">15</div> </div> <div class="footmain"> <div v-if="false" class="">未選購商品</div> <div class="ih30 fs1-2">¥ 3205</div> <div class="ih20">配送費 ¥5</div> </div> </div> <div class="footright"> <span >¥20起送</span> <span v-if="false">還差¥15起送</span> <span v-if="false">去結算</span> </div> </div> </transition>
這時發現商品數量沒有計算,目前是寫死的15,在計算屬性computed
中添加計算
computed:{ //計算屬性 mycarshopnum:function(){ var num=0; for(var i=0;i<this.mycar.length;i++){ num+=this.mycar[i].num; } return num } },
在footdiv
中的rednum
調用
<div v-if="mycar" class="rednum">{{mycarshopnum}}</div>
ok!運行試試
解決!
1.能夠看到,除了商品數量,其餘全是假的,我們如今寫活。
在computed
中添加商品價格的計算(piecewise_agent_fee.tips
爲配送費,float_minimum_order_amount
爲起送費,在商家詳情的API中,我們之前已經獲取)
computed:{ //計算屬性 //計算商品數量 mycarshopnum:function(){ var num=0; for(var i=0;i<this.mycar.length;i++){ num+=this.mycar[i].num; } return num }, //計算商品價格(商品只有一個種類) mycarshoppic:function(){ var num=0; for(var i=0;i<this.mycar.length;i++){ num+=(this.mycar[i].shop.specfoods[0].price*this.mycar[i].num); } return num }, //判斷商家起送價與目前購物車價格 shoppicbig:function(){ if(this.mycar){ if(this.mycarshoppic>=this.shopinfo.float_minimum_order_amount){ return 1 }else{ return 2 } }else{ return false } } },
footdiv修改以下
<transition name="left"> <div v-if="footdiv" class="foot" :class="{on:mycar.length>=1}"> <div class="footleft"> <div class="footlogo"> <icon name="footcar" class="footicon"></icon> <div v-if="mycar" class="rednum">{{mycarshopnum}}</div> </div> <div class="footmain"> <div v-if="!mycar" class="">未選購商品</div> <div v-if="mycar" class="ih30 fs1-2">¥ {{mycarshoppic}}</div> <div v-if="mycar" class="ih20">{{this.shopinfo.piecewise_agent_fee.tips}}</div> </div> </div> <div class="footright" :class="{on:shoppicbig==1}"> <span v-if="!mycar">¥{{this.shopinfo.float_minimum_order_amount}}起送</span> <span v-if="shoppicbig==2">還差¥{{this.shopinfo.float_minimum_order_amount-mycarshoppic}}起送</span> <span v-if="shoppicbig==1">去結算</span> </div> </div> </transition>
運行試試
如今只有購物車顯示總數量,每一個商品顯示幾個並無。
1.樣式
<transition name="right"> <span class="ih20"> <span><icon class="addicon" name="offline"></icon></span> <span class="ih20 inblock y-4">15</span> </span> </transition>
由於商品數量爲0時,減號也該沒有,因此商品數量與減號寫在一個動畫內了,樣式以下
2.判斷商品數量。
如今商品的信息是從接口請求到後直接渲染在頁面,沒有作任何處理。如今咱們要把商品信息與購物車的信息結合一下,在computed
寫函數(shopmean
是從接口請求到的商品信息,在前幾章已經請求到,未作任何處理。specfoods
是商品的型號,這裏默認只有一個)
//商品與購物車數量結合 getshopnum:function(){ for(var i=0;i<this.shopmean.length;i++){ for(var k=0;k<this.shopmean[i].foods.length;k++){ for( var h=0;h<this.mycar.length;h++){ if(this.shopmean[i].foods[k].specfoods[0]._id==this.mycar[h].shop.specfoods[0]._id){ this.shopmean[i].foods[k].mynum=this.mycar[h].num; } } } } return this.shopmean }
再而後咱們在頁面渲染數據時,只須要把
v-for="item in shopmean"
改爲
v-for="item in getshopnum"
便可。
最後判斷減號與數量的顯示隱藏
<transition name="right"> <span v-if="items.mynum" class="ih20"> <span><icon class="addicon" name="offline"></icon></span> <span class="ih20 inblock y-4">{{items.mynum}}</span> </span> </transition>
運行試試
除了動畫沒有運行,其餘的完美!
1.刪除點擊事件在dome綁定
<transition name="right"> <span v-if="items.mynum" class="ih20"> <span @click="removecar(items)"><icon class="addicon" name="offline"></icon></span> <span class="ih20 inblock y-4">{{items.mynum}}</span> </span> </transition>
在methods
中寫函數
removecar:function(e){ for(var i=0;i<this.mycar.length;i++){ if(this.mycar[i].shop.specfoods[0]._id==e.specfoods[0]._id){ this.mycar[i].num==1?this.mycar.splice(i,1):(this.mycar[i].num=this.mycar[i].num-1); break; } } localStorage.setItem("mycar",JSON.stringify(this.mycar)); }
注意
這裏要改一下計算屬性中的getshopnum
函數。我們在剛開始寫時,只是把商品列表跟購物車列表循環,當ID相同時在商品列表添加屬性mynum
存儲商品在購物車數量,不相同時不做操做。可是,咱們作了減商品的功能後,當商品數量爲1時,減一後購物車清除該商品,而後經過計算屬性中的getshopnum
函數與商品列表循環,結果由於購物車已經清除該商品而函數找不到相同ID不做任何操做,但商品列表的該商品數量仍爲一,因此當ID不相同時咱們給商品列表自定義屬性mynum
爲0便可,將computed
中的getshopnum
修改成
//商品與購物車數量結合 getshopnum:function(){ for(var i=0;i<this.shopmean.length;i++){ for(var k=0;k<this.shopmean[i].foods.length;k++){ var isadd=true; //判斷該商品是否在購物車 for( var h=0;h<this.mycar.length;h++){ if(this.shopmean[i].foods[k].specfoods[0]._id==this.mycar[h].shop.specfoods[0]._id){ this.shopmean[i].foods[k].mynum=this.mycar[h].num; isadd=false; break; } } if(isadd){ this.shopmean[i].foods[k].mynum=0; } } } return this.shopmean }
注意
當購物車清空時,mycar
已存在而不是剛開始的空,因此購物車div裏的元素顯示隱藏要修改成判斷mycar
的長度而不是是否爲空
<transition name="left"> <div v-if="footdiv" class="foot" :class="{on:mycar.length>=1}"> <div class="footleft"> <div class="footlogo"> <icon name="footcar" class="footicon"></icon> <div v-if="mycar.length" class="rednum">{{mycarshopnum}}</div> </div> <div class="footmain"> <div v-if="!mycar.length" class="">未選購商品</div> <div v-if="mycar.length" class="ih30 fs1-2">¥ {{mycarshoppic}}</div> <div v-if="mycar.length" class="ih20">{{this.shopinfo.piecewise_agent_fee.tips}}</div> </div> </div> <div class="footright" :class="{on:shoppicbig==1}"> <span v-if="!mycar">¥{{this.shopinfo.float_minimum_order_amount}}起送</span> <span v-if="shoppicbig==2">還差¥{{this.shopinfo.float_minimum_order_amount-mycarshoppic}}起送</span> <span v-if="shoppicbig==1">去結算</span> </div> </div> </transition>
運行試試
咱們只須要在getshopnum
給商品判斷購物車中給商品數量時,給該商品的分類也加上該商品的數量便可。修改以下
//商品與購物車數量結合 getshopnum:function(){ for(var i=0;i<this.shopmean.length;i++){ var thisnum=0; for(var k=0;k<this.shopmean[i].foods.length;k++){ var isadd=true; //判斷該商品是否在購物車 for( var h=0;h<this.mycar.length;h++){ if(this.shopmean[i].foods[k].specfoods[0]._id==this.mycar[h].shop.specfoods[0]._id){ this.shopmean[i].foods[k].mynum=this.mycar[h].num; thisnum+=this.mycar[h].num; isadd=false; break; } } if(isadd){ this.shopmean[i].foods[k].mynum=0; } } this.shopmean[i].mynum=thisnum; } return this.shopmean }
結果以下
ok!購物車表面功夫寫完了,下面升級購物車。
注意
購物車應該在渲染頁面事就獲取數據,因此在mounted
中添加
//獲取購物車信息 if(localStorage.getItem("mycar")){ that.mycar=JSON.parse(localStorage.getItem("mycar")); }
最終shop.vue代碼修改以下
<template> <div id="shop" class="bgfff"> <transition name="left"> <div v-if="myrouter" class="big"> <div class="topbg"> <img class="topbgimg" :src="imgpath+shopinfo.image_path"> </div> <div class="shoptop"> <div class="toptop ih30"> <router-link to="/miste"> <icon class="backicon" name="back"></icon> </router-link> <span class="right"> <icon class="backicon2" name="cart"></icon> <icon class="backicon2" name="more"></icon> </span> </div> <div class="topfoot"> <div class="topleft"> <img :src="imgpath+shopinfo.image_path"> </div> <div class="topright nowarp"> <router-link to="shop/shopDetail"> <div class="foota"> <div class="footamain fs1-2 nowarp">{{shopinfo.name}}</div> <icon name="right" class="icon3"></icon> </div> </router-link> <div class="footb nowarp"> <div class="nowarp">公告:{{shopinfo.promotion_info}}</div> </div> <div class="footc"> <span class="footcmain"><span v-if="shopinfo.delivery_mode">{{shopinfo.delivery_mode.text}}•</span><span>約{{shopinfo.order_lead_time}}</span></span> </div> </div> </div> </div> <div class="shopmid mgtop10"> <div @click="modal=true" v-if="shopinfo.activities" class="midtop"><span class="te mgr5">{{shopinfo.activities[0].icon_name}}</span><span>{{shopinfo.activities[0].description}}</span><span class="right">{{shopinfo.activities.length}}個活動 <icon name="down" class="icon4"></icon></span></div> <div class="mytab"> <div @click="footdiv=shoporscore=true" :class="{ on:shoporscore }">商品</div> <div @click="footdiv=shoporscore=false" :class="{ on:!shoporscore }">評價{{shopinfo.rating}}分</div> </div> </div> <transition name="left"> <div v-if="shoporscore" class="shopmain"> <div class="mianleft"> <div v-for="(item,index) in getshopnum" @click="itemgo(index)" :class="{on:index==shopon}" class="relative leftdiv"> <div> <icon v-if="index==0" class="icon5" name="hot"></icon> <icon v-if="index==1" class="icon5" name="discount"></icon> <span class="fs0-8">{{item.name}}</span> <span v-if="item.mynum" class="rednum2">{{item.mynum}}</span> </div> </div> </div> <div class="mainright"> <div class="item" v-for="item in getshopnum"> <div class="itemtop padtop10 ih30 after"> <span class="fs15">{{item.name}}</span> <span class="fs0-8 col9f">{{item.description}}</span> </div> <div class="itemmain"> <div v-for="items in item.foods" class="after"> <router-link to="/shop/foodDetail"> <div class="iteminfo"> <div class="infoimgbox"> <img :src="imgpath+items.image_path"> </div> <div class="inforight nowarp"> <div class="colblack fs15 ih20 nowarp">{{items.name}}</div> <div class="ih15 col9f"><span class="fs10 mgl">{{items.tips}}</span></div> <div class="ih15"><span v-if="false" class="fs10 mgl"><span class="zk">包裝費</span><span class="yh">{{}}</span></span></div> <div class="ih20"> <span class="colred fs12">¥</span> <span class="colred mgr5">{{items.specfoods[0].price}}</span> <span v-if="items.specfoods[0].original_price" class="fs12 col9f midline">¥56</span> </div> </div> </div> </router-link> <div class="iteminfofoot ih20"> <transition name="top"> <span v-if="items.mynum" class="ih20"> <span @click="removecar(items)"><icon class="addicon" name="offline"></icon></span> <span class="ih20 inblock y-4">{{items.mynum}}</span> </span> </transition> <span v-if="items.specfoods.length==1" @click="addcar(items)" class=""><icon name="add" class="addicon"></icon></span> <span class="fs12 right gz" v-if="items.specfoods.length>1">選規則</span> </div> </div> </div> </div> </div> </div> </transition> <transition name="right"> <div class="score" v-if="!shoporscore"> <div class="scoretop"> <div class="scoretopleft"> <div class="fs1-2 colf60">{{shopinfo.rating}}</div> <div class="fs15 col9f">綜合評價</div> <div class="fs0-8 col9f">高於周邊商家{{parseInt(scorerating.compare_rating*100)}}%</div> </div> <div class="scoretopright"> <div><span class="fs15 col9f mgr5">評價服務</span><stars :num="scorerating.service_score.toFixed(1)"></stars><span class="colf60 right">{{scorerating.service_score.toFixed(1)}}</span></div> <div><span class="fs15 col9f mgr5">菜品評價</span><stars :num="scorerating.food_score.toFixed(1)"></stars><span class="colf60 right">{{scorerating.food_score.toFixed(1)}}</span></div> <div><span class="fs15 col9f mgr5">送達時間</span><span class="fs15 colf60">{{scorerating.deliver_time}}分鐘</span></div> </div> </div> <div class="scoremain"> <div class="scoremaintop after"> <div v-for="(item,index) in scoretags" class="ih30 fs0-8" :class="{sty2:item.unsatisfied,sty1:!(item.unsatisfied),on:index==scoreindex}">{{item.name}}({{item.count}})</div> </div> <div class="scoremaininfo"> <div v-for="item in score" class="scoreitem after"> <div class="scoreitemleft"> <img :src="imgaddpath(item.avatar)" > </div> <div class="scoreitemright fs12 col9f"> <div> <span>{{item.username}}</span> <span class="right">{{item.rated_at}}</span> </div> <div> <stars :num="item.rating_star"></stars> </div> <div> {{item.time_spent_desc}} </div> <div class="scoreimgbox"> <img v-for="itema in item.item_ratings" :src="imgaddpath(itema.image_hash)"> </div> <div class="namebox"> <div v-for="itemb in item.item_ratings">{{itemb.food_name}}</div> </div> </div> </div> </div> </div> </div> </transition> <transition name="top"> <div v-if="modal" class="modal flex2 colfff pad10"> <div class="modaltop flex1"> <div> <div class="modaltitle"> {{shopinfo.name}} </div> <div class="modalmid"> <div class="modal_title ih30"><span>優惠信息</span></div> <div> <div v-if="shopinfo.activities" v-for="item in shopinfo.activities" class="midtop"><span class="te mgr5">{{item.icon_name}}</span><span>{{item.description}}</span></div> </div> </div> <div class="modalinfo mgtop40"> <div class="modal_title ih30"><span>商家公告</span></div> <div> {{shopinfo.promotion_info}} </div> </div> </div> </div> <div @click="modal=false" class="modalfoot"> <span>X</span> </div> </div> </transition> <load v-if="num!=1"></load> </div> </transition> <transition name="left"> <div v-if="footdiv" class="foot" :class="{on:mycar.length>=1}"> <div class="footleft"> <div class="footlogo"> <icon name="footcar" class="footicon"></icon> <div v-if="mycar.length" class="rednum">{{mycarshopnum}}</div> </div> <div class="footmain"> <div v-if="!mycar.length" class="">未選購商品</div> <div v-if="mycar.length" class="ih30 fs1-2">¥ {{mycarshoppic}}</div> <div v-if="mycar.length" class="ih20">{{this.shopinfo.piecewise_agent_fee.tips}}</div> </div> </div> <div class="footright" :class="{on:shoppicbig==1}"> <span v-if="shoppicbig==3">¥{{this.shopinfo.float_minimum_order_amount}}起送</span> <span v-if="shoppicbig==2">還差¥{{this.shopinfo.float_minimum_order_amount-mycarshoppic}}起送</span> <span v-if="shoppicbig==1">去結算</span> </div> </div> </transition> <router-view></router-view> </div> </template> <script> import stars from '../../components/stars/stars' import load from '../../components/load/load' export default { data () { return { mycar:"", //個人購物車 footdiv:true, //腳部購物車是否顯示 shopon:0, //商品種類選中的哪一個 imgpath:'http://cangdu.org:8001/img/', //商家頭像的路徑地址path shopinfo:"", //商家信息 shopmean:"", //食品信息 shoporscore:true, //商家仍是評價 score:"", //評價信息 scorerating:"", //評價分數 scoretags:"", //評價分類 scoreindex:0, //選中第幾個評價分類 num:1, modal:false, //模態框顯示隱藏 myrouter:true, //是否顯示big div } }, components:{ //註冊組件 stars, load }, mounted:function(){ //生命週期 var that=this; //獲取購物車信息 if(localStorage.getItem("mycar")){ that.mycar=JSON.parse(localStorage.getItem("mycar")); } that.num=that.num-5; //餐館詳情 this.$http.get('http://cangdu.org:8001/shopping/restaurant/'+this.$store.state.shopid+'').then(response => { console.log(response); this.shopinfo=response.body; that.num=that.num+1; }, response => { that.num=that.num+1; console.log(response); }); //食品詳情 this.$http.get('http://cangdu.org:8001/shopping/v2/menu?restaurant_id='+this.$store.state.shopid+'').then(response => { console.log(response); that.num=that.num+1; this.shopmean=response.body; }, response => { that.num=that.num+1; console.log(response); }); //評論詳情 this.$http.get('http://cangdu.org:8001/ugc/v2/restaurants/'+this.$store.state.shopid+'/ratings?offset=0&limit=10').then(response => { console.log(response); that.num=that.num+1; this.score=response.body; }, response => { that.num=that.num+1; console.log(response); }); //評論分數 this.$http.get('http://cangdu.org:8001/ugc/v2/restaurants/'+this.$store.state.shopid+'/ratings/scores').then(response => { console.log(response); this.scorerating=response.body; that.num=that.num+1; }, response => { console.log(response); that.num=that.num+1; }); //評論分類 this.$http.get('http://cangdu.org:8001/ugc/v2/restaurants/'+this.$store.state.shopid+'/ratings/tags').then(response => { console.log(response); this.scoretags=response.body; that.num=that.num+1; }, response => { console.log(response); that.num=that.num+1; }); let mydiv=document.querySelector('.mainright'); mydiv.addEventListener('scroll', this.handleScroll); }, computed:{ //計算屬性 //計算商品數量 mycarshopnum:function(){ var num=0; for(var i=0;i<this.mycar.length;i++){ num+=this.mycar[i].num; } return num }, //計算商品價格(商品只有一個種類) mycarshoppic:function(){ var num=0; if(this.mycar.length){ for(var i=0;i<this.mycar.length;i++){ num+=(this.mycar[i].shop.specfoods[0].price*this.mycar[i].num); } }; return num; }, //判斷商家起送價與目前購物車價格 shoppicbig:function(){ if(this.mycarshoppic>=this.shopinfo.float_minimum_order_amount){ return 1 }else if(this.mycarshoppic==0){ return 3 }else{ return 2 } }, //商品與購物車數量結合 getshopnum:function(){ for(var i=0;i<this.shopmean.length;i++){ var thisnum=0; for(var k=0;k<this.shopmean[i].foods.length;k++){ var isadd=true; //判斷該商品是否在購物車 for( var h=0;h<this.mycar.length;h++){ if(this.shopmean[i].foods[k].specfoods[0]._id==this.mycar[h].shop.specfoods[0]._id){ this.shopmean[i].foods[k].mynum=this.mycar[h].num; thisnum+=this.mycar[h].num; isadd=false; break; } } if(isadd){ this.shopmean[i].foods[k].mynum=0; } } this.shopmean[i].mynum=thisnum; } return this.shopmean } }, methods:{ //函數 imgaddpath:function(e){ return "https://fuss10.elemecdn.com/"+e+".jpeg" }, itemgo:function(index){ this.shopon=index; document.querySelector('.mainright').scrollTop=document.querySelectorAll('.itemtop')[index].offsetTop; }, handleScroll:function(){ var mydiv=document.querySelectorAll('.item'); for(var i =0;i<mydiv.length;i++){ if(mydiv[i].offsetTop>document.querySelector('.mainright').scrollTop-10&&mydiv[i].offsetTop<document.querySelector('.mainright').scrollTop+10){ this.shopon=i; } } }, newpage:function(){ this.myrouter=(this.$route.path=="/shop"?true:false); this.footdiv=(((this.$route.path=="/shop"&&this.shoporscore)||this.$route.path=="/shop/foodDetail")?true:false); }, gofoodDetail:function(){ this.$router.push("/shop/foodDetail"); }, addcar:function(e){ var that=this; if(localStorage.getItem("mycar")){ var mycar=JSON.parse(localStorage.getItem("mycar")); var addok=true; //數據是否添加 for(var i =0;i<mycar.length;i++){ if(mycar[i].shop.item_id==e.item_id&&mycar[i].shop.category_id==e.category_id&&mycar[i].shop.restaurant_id==e.restaurant_id){ mycar[i].num=mycar[i].num+1; addok=false; break; } } if(addok){ mycar.push({"shop":e,"num":1}); } that.mycar=mycar; localStorage.setItem("mycar",JSON.stringify(mycar)); }else{ var mycar=[{"shop":e,"num":1}]; that.mycar=mycar; localStorage.setItem("mycar",JSON.stringify(mycar)); }; }, removecar:function(e){ for(var i=0;i<this.mycar.length;i++){ if(this.mycar[i].shop.specfoods[0]._id==e.specfoods[0]._id){ this.mycar[i].num==1?this.mycar.splice(i,1):(this.mycar[i].num=this.mycar[i].num-1); break; } } localStorage.setItem("mycar",JSON.stringify(this.mycar)); } }, watch:{ "$route":"newpage", } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> .big{ display:-webkit-box; -webkit-box-orient:vertical; height:100vh; } .shoptop{ height:120px; background-color: rgba(119,103,137,.43); box-sizing:border-box; padding:10px 10px 0px 10px; position: relative; } .topbg{ position: absolute; width:100%; height:120px; left:0px; right:0px; overflow:hidden; } .topbgimg{ width:100%; filter: blur(10px); } .backicon{ height:30px; width:30px; } .backicon2{ height:25px; width:25px; } .toptop{ margin-bottom:10px; } .topfoot{ height:70px; display:flex; } .topleft{ height:80px; width:80px; background-color:#3c3c3c; margin-right:10px; border-radius:3px; box-shadow:0 0 5px #3c3c3c; } .topleft>img{ max-width:100%; max-height:100%; border-radius:3px; } .topright,.topleft{ float:left; } .topright{ height:100%; flex:1; } .foota{ height:30px; color:white; line-height:30px; display:flex; } .icon3{ width:20px; height:20px; margin-top:5px; } .footc{ height:20px; line-height:20px; font-size:12px; } .footb{ font-size:12px; color:white; } .footcmain{ background-color:#0097FF; color:white; padding:0px 5px; } .shopmid{ padding:10px 10px 0px 10px; border-bottom:2px solid #F8F8F8; } .midtop{ font-size:12px; } .te{ background-color:#F08449; padding:0px 1px; color:white; } .mytab{ overflow:hidden; margin-top:10px; } .mytab>div{ float:left; padding-bottom:10px; margin-right:10px; border-bottom:2px solid white; } .mytab>div.on{ color:#0B89FF; border-color:#0B89FF; } .leftdiv{ width:60px; padding:0px 10px; color:#727272; background-color:#F8F8F8; } .leftdiv>div{ padding:15px 0px; border-bottom:1px solid #F1F1F1; } .leftdiv.on{ background-color:white; color:#080808; } .leftdiv.on>div{ border:0px; } .icon5{ width:15px; height:15px; } .mianleft{ width:80px; box-sizing:border-box; overflow:scroll; } .shopmain{ -webkit-box-flex:1; display:-webkit-box; overflow:hidden; margin-bottom:50px; } .mainright{ -webkit-box-flex:1; overflow:scroll; padding-left:10px; position: relative; } .foot{ height:50px; line-height:50px; background-color:#594C46; display:flex; position:fixed; bottom:0px; left:0px; width:100%; } .foot.on .footicon{ color:#fff; } .foot.on .footmain{ color:#fff; } .foot.on .footright{ color:#fff; } .foot.on .footlogo{ background-color:#3190E8; } .footleft{ flex:2; display:flex; } .footright{ flex:1; text-align:center; color:#B7B7B7; background-color:#61686A; } .footright.on{ background-color:#4CD964; color:white; } .footlogo{ text-align:center; width:50px; height:50px; border-radius:50%; background-color:#515151; margin:0px 10px; border:3px solid #444446; transform:translatey(-15px) } .footicon{ color:#8a8a8a; width:40px; height:40px; margin-top:7px; } .footmain{ height:50px; color:#ADADAD; font-size:0.8rem; } .itemmain{ padding-right:10px; } .iteminfo{ height:70px; display:flex; padding:10px 0px; } .infoimgbox{ width:70px; height:70px; margin-right:5px; background-color:red; } .infoimgbox>img{ width:100%; height:100%; } .inforight{ flex:1; } .ih20{ height:20px; line-height:20px; } .ih15{ height:15px; line-height:15px; } .addicon{ width:20px; height:20px; } .zk{ background-color:#FF5F15; padding:0px 3px; color:white; border:1px solid #FF5F15; } .yh{ padding:0px 3px; color:#FF5F15; border:1px solid #FF5F15; } .gz{ display:inline-block; background-color:#3190E8; color:white; padding:0px 2px; border-radius:2px; } .scoretop{ display:flex; padding:0px 10px 10px 10px; border-bottom:10px solid #F5F5F5; } .scoretopleft{ flex:2; text-align:center; } .scoretopright{ flex:3; } .scoretopright>div{ display:flex; } .scoremain{ padding:0px 10px; } .scoremaintop{ padding:10px 0px 5px 0px; display:flex; flex-wrap:wrap; } .scoremaintop>div{ padding:0px 8px; border-radius:5px; margin-right:5px; margin-bottom:5px; } .sty1{ background-color:#EBF5FF; color:#9f9f9f; } .sty1.on{ background-color:#3190E8; color:#fff; } .sty2{ background-color:#F5F5F5; color:#AFAFAF; } .scoreitem{ display:flex; margin-top:10px; } .scoreitemleft{ width:50px; height:50px; margin-right:10px; } .scoreitemleft>img{ width:100%; border-radius:50%; } .scoreitemright{ flex:1; } .namebox{ display:flex; flex-wrap: wrap; } .namebox>div{ border:1px solid; padding:3px 3px; margin-right:5px; border-radius:3px; margin-bottom:5px; } .score{ padding-top:10px; flex:1; overflow-y: scroll; } .scoreimgbox>img{ width:4rem; height:4rem; margin-right:10px; } .modal{ box-sizing:border-box; width:100vw; height:100vh; background-color:#262626; position:fixed; top:0px; left:0px; z-index:10; } .modaltop{ overflow: scroll; } .modaltitle{ margin:20px 0px; text-align:center; font-size:1.5rem; } .modal_title{ text-align:center; margin:10px; } .modal_title>span{ padding:2px 5px; border:1px solid #fff; border-radius:5px; } .modalfoot{ width:100%; margin-bottom:10px; justify-content:flex-end; text-align:center; } .modalfoot>span{ display: inline-block; border:1px solid #fff; border-radius:50%; width:30px; padding:5px; height:30px; ling-height:30px; font-size:25px; } .iteminfofoot{ position: absolute; bottom: 10px; right: 0px; } .hidden{ overflow: hidden; } .rednum{ position: absolute; top:-3px; right:-5px; border-radius:50%; background-color:red; color:white; height:18px; width:18px; text-align:center; line-height:18px; font-size:12px; } .y-4{ transform: translateY(-4px); } .rednum2{ position: absolute; top:0px; right:0px; border-radius:50%; background-color:red; color:white; height:15px; width:15px; text-align:center; line-height:15px; font-size:12px; } </style>
引入的全局css以下
body{ margin: 0px; height: 100vh; background-color: #f5f5f5; } *{ text-decoration:none; } .fixed{ position: fixed; top: 0px; width: 100%; z-index: 5; } .ih40{ height: 40px; line-height: 40px; } .ih30{ height: 30px; line-height: 30px; } .ih50{ height: 50px; line-height: 50px; } .bgcol{ background-color:#26a2ff; } .bgfff{ background-color: #fff; } .bgf5{ background-color:#F5F5F5; } .fs0-8{ font-size: 0.8rem !important; } .fs1-2{ font-size: 1.2rem; } .fs15{ font-size: 15px; } .fs12{ font-size: 12px; } .fs10{ font-size: 12px; transform: scale(.8); display:inline-block; } .mgr{ transform-origin:100% 50% 0;/*改變縮放基點*/ } .mgl{ transform-origin:0 50% 0;/*改變縮放基點*/ } .colfff{ color: #fff; } .col9f{ color: #9F9F9F; } .colf60{ color: #FF6600; } .col{ color: #26a2ff; } .colred{ color:#FE3D3D; } .colblack{ color: black; } .pad10{ padding: 10px; } .padlr10{ padding:0px 10px 0px 10px; } .padtop10{ padding-top:10px; } .padtop40{ padding-top:40px; } .padtop50{ padding-top:50px; } .padbot10{ padding-bottom:10px; } .padr10{ padding-right: 10px; } .mgtop5{ margin-top: 5px; } .mgtop40{ margin-top: 40px; } .mgtop50{ margin-top: 50px; } .mgtop10{ margin-top: 10px; } .mgbot10{ margin-bottom: 10px; } .mgr5{ margin-right: 5px; } .w15{ width: 15px; height: 15px; } .w60{ width: 60px; height: 60px; } .w100{ width: 100%; } .radius50{ border-radius: 50%; } .inblock{ display: inline-block; } .flex{ display: flex; } .flex2{ display: flex; flex-direction:column; } .flex1{ flex: 1; } .ovhid{ overflow: hidden; } .box{ box-sizing: border-box; } .right{ float: right; } .clear{ clear: both; } .relative{ position: relative; } .left{ float: left; } .midline{ text-decoration: line-through; } .nowarp{ white-space:nowrap; /* 不換行 */ overflow:hidden; /* 內容超出寬度時隱藏超出部分的內容 */ text-overflow:ellipsis; /* 當對象內文本溢出時顯示省略標記(...) ;需與overflow:hidden;一塊兒使用。*/ } /*一像素分割線*/ .after{ position: relative; } .after::after{ content: " "; position: absolute; left: 0; bottom: 0; width: 100%; height: 1px; background-color: #e4e4e4; -webkit-transform-origin: left bottom; transform-origin: left bottom; } /* 2倍屏 */ @media only screen and (-webkit-min-device-pixel-ratio: 2.0) { .after::after { -webkit-transform: scaleY(0.5); transform: scaleY(0.5); } } /* 3倍屏 */ @media only screen and (-webkit-min-device-pixel-ratio: 3.0) { .after::after { -webkit-transform: scaleY(0.33); transform: scaleY(0.33); } } /* 組件動畫 */ /* 左進左出 */ .left-enter-active{ animation-name: left-in; animation-duration: .2s; animation-timing-function:linear; } .left-leave-active{ animation-name: left-out; animation-timing-function:linear; animation-duration: .2s; } @keyframes left-in { 0% { transform: translate3d(-100%, 0, 0); } 50% { transform: translate3d(-50%, 0, 0); } 100% { transform: translate3d(0, 0, 0); } } @keyframes left-out { 0% { transform: translate3d(0, 0, 0); } 50% { transform: translate3d(-50%, 0, 0); } 100% { transform: translate3d(-100%, 0, 0); } } /* 右進右出 */ .right-enter-active{ animation-name: right-in; animation-duration: .2s; animation-timing-function:linear; } .right-leave-active{ animation-name: right-out; animation-timing-function:linear; animation-duration: .2s; } @keyframes right-in { 0% { transform: translate3d(100%, 0, 0); } 50% { transform: translate3d(50%, 0, 0); } 100% { transform: translate3d(0, 0, 0); } } @keyframes right-out { 0% { transform: translate3d(0, 0, 0); } 50% { transform: translate3d(50%, 0, 0); } 100% { transform: translate3d(100%, 0, 0); } } /* 上進上出 */ .top-enter-active{ animation-name: top-in; animation-duration: .2s; animation-timing-function:linear; } .top-leave-active{ animation-name: top-out; animation-timing-function:linear; animation-duration: .2s; } @keyframes top-in { 0% { transform: translate3d(0, -100%, 0); } 50% { transform: translate3d(0, -50%, 0); } 100% { transform: translate3d(0, 0, 0); } } @keyframes top-out { 0% { transform: translate3d(0, 0, 0); } 50% { transform: translate3d(0, -50%, 0); } 100% { transform: translate3d(0, -100%, 0); } } /* 淡進淡出 */ .opacity-enter-active{ animation-name: opacity-in; animation-duration: .2s; animation-timing-function:linear; } .opacity-leave-active{ animation-name: opacity-out; animation-timing-function:linear; animation-duration: .2s; } @keyframes opacity-in { 0% { opacity:0; } 50% { opacity:0.5; } 100% { opacity:1; } } @keyframes opacity-out { 0% { opacity:1; } 50% { opacity:0.5; } 100% { opacity:0; } }
下面來改造購物車