每個步驟都有對應的一份代碼和截圖,按部就班。
npm install -g cnpm --registry=https://registry.npm.taobao.org
npm install vue-cli -g
vue init webpack meituanwaimai
cd meituan
cnpm install
cnpm run dev
http://localhost:8080
<template> <ul class="tab-bar"> <li ><i class="icon-index"></i><span>首頁</span></li> <li ><i class="icon-order"></i><span>訂單</span></li> <li ><i class="icon-mine"></i><span>個人</span></li> </ul> </template> <script> export default { components: {}, data () { return {} }, props: {}, watch: {}, methods: {}, filters: {}, computed: {}, created () {}, mounted () {}, destroyed () {} } </script> <style scoped> .tab-bar { position: fixed; bottom: 0; width: 100%; height: 49px; text-align: center; border-top: 1px solid rgb(182, 182, 182); background-color: #fcfcfc; display: flex; flex-direction: row; } li { flex: 1; color: #999; } i { display: block; width: 25px; height: 25px; margin: 3px auto; background: url('./tabbarBg.png') no-repeat; background-size: 25px auto; } span { display: block; font-size: 12px; } .icon-index { background-position: 0 -75px; } .icon-order { background-position: 0 -25px; } .icon-mine { background-position: 0 -125px; } </style>
cnpm install vue-router --save
css
本例的vue-router就是一個vue-router最簡單的用法,把每一個組件對應路徑就行了。而後在main.js中引入它,而後綁定在vue實例中就能夠了。
import Vue from 'vue' import Router from 'vue-router' import Index from '@/components/index/index' import Order from '@/components/order/order' import Mine from '@/components/mine/mine' Vue.use(Router) export default new Router({ routes: [ // 根路徑 { path: '/', redirect: '/index' }, // 首頁 { path: '/index', component: Index }, // 訂單 { path: '/order', component: Order }, // 個人 { path: '/mine', component: Mine } ] })
選中樣式會默認加上router-link-active樣式,只要在這個樣式中把選中圖片替換掉就好(這裏是改變圖片位置)。把li替換成router-link,tag表示對應的標籤,to表示點擊它會router-view會顯示的組件html
<template> <ul class="tab-bar"> <router-link tag="li" to="/index"><i class="icon-index"></i><span>首頁</span></router-link> <router-link tag="li" to="/order"><i class="icon-order"></i><span>訂單</span></router-link> <router-link tag="li" to="/mine"><i class="icon-mine"></i><span>個人</span></router-link> </ul> </template> <script> export default { components: {}, data () { return {} }, props: {}, watch: {}, methods: {}, filters: {}, computed: {}, created () {}, mounted () {}, destroyed () {} } </script> <style scoped> .tab-bar { position: fixed; bottom: 0; width: 100%; height: 49px; text-align: center; border-top: 1px solid rgb(182, 182, 182); background-color: #fcfcfc; display: flex; flex-direction: row; } li { flex: 1; color: #999; } i { display: block; width: 25px; height: 25px; margin: 3px auto; background: url('./tabbarBg.png') no-repeat; background-size: 25px auto; } span { display: block; font-size: 12px; } .icon-index { background-position: 0 -75px; } .icon-order { background-position: 0 -25px; } .icon-mine { background-position: 0 -125px; } .router-link-active { color: #333; } .router-link-active .icon-index { background-position: 0 -50px; } .router-link-active .icon-order { background-position: 0 0px; } .router-link-active .icon-mine { background-position: 0 -100px; } </style>
在reset.css中把html、body高度設置爲100%,把app組件的高度也設置爲100%就能全屏高度
cnpm install mint-ui --save
vue
import MintUI from 'mint-ui' import 'mint-ui/lib/style.css' Vue.use(MintUI)
<div class="slider"> <mt-swipe :auto="3000"> <mt-swipe-item v-for="item in swipeData" :key="item.pic"> <img :src="item.pic"> </mt-swipe-item> </mt-swipe> </div> data () { return { swipeData: [ {pic: require('./img/swipe/1.jpg')}, {pic: require('./img/swipe/2.jpg')} ], } } .slider { height: 170px; font-size: 30px; text-align: center; overflow: hidden; } .slider img { width: 100%; }
data () { return { swipeData: [ { pic: require('./img/swipe/1.png') }, // { // pic: require('./img/swipe/1.png') // } ], types:[ { icon: require('./img/types/ms.png'), title: '美食' }, { icon: require('./img/types/mtcs.png'), title: '美團超市' }, { icon: require('./img/types/sxgs.png'), title: '生鮮果蔬' }, { icon: require('./img/types/tdyp.png'), title: '甜點飲品' }, { icon: require('./img/types/mtzs.png'), title: '美團專送' }, { icon: require('./img/types/zcyx.png'), title: '正餐優選' }, { icon: require('./img/types/kcxc.png'), title: '快餐小吃' }, { icon: require('./img/types/hbps.png'), title: '漢堡披薩' } ] } }
<template> <div class="types-item"> <img src="../../index/img/types/hbps.png" > <span>漢堡披薩</span> </div> </template> <style scoped> .types-item { float: left; width: 25%; padding-top: 14px; } .types-item img { display: block; width: 50px; margin: 0 auto 12px; } .types-item span { display: block; font-size: 14px; line-height: 14px; text-align: center; color: #2f2f2f; } </style>
<!-- 種類 --> <div class="types"> <types-item ></types-item> <types-item ></types-item> <types-item ></types-item> <types-item ></types-item> <types-item ></types-item> <types-item ></types-item> <types-item ></types-item> <types-item ></types-item> </div> import typesItem from '@/components/base/types-item/types-item'
引入.vue文件時使用的@是在webpack.base.conf.js文件的alias位置配置的,在須要寫路徑時均可以在這裏配置絕對路勁的簡寫方式
index.vue <div class="types"> <types-item v-for="item in types" :icon="item.icon" :title="item.title" :key="item.title"></types-item> </div> types-item.vue <template> <div class="types-item"> <img :src="icon" > <span v-text="title"></span> </div> </template> props: { icon:{ type:String, default:'' }, title:{ type:String, default:'' } },
這裏數據僅僅爲3條,項目中複製了4分共12條數據,列表中須要須要對數據判斷的幾個地方:node
shopList: [ { "id": 1000,//id "type":1,//1表明新店、2表明品牌店、0表明都不是 "name": "你的名字",//店名 "delivery_type": 1,//1表明美團專送,0表明不是 "pic_url": "http://p0.meituan.net/0.84.63/xianfu/54c60749841a6612df373dc259e8da73108176.jpg",//圖片地址 "avg_delivery_time": 30,//平均送達時間 "delivery_distance": 2032,//平均送達距離(單位爲米,超過一公里要轉化成公里) "min_price": 20,//起送價 "delivery_price": 3,//配送費 "wm_poi_score": 4.7,//評分 "month_sale_num": 33,//月售 "shop_discount": { "code":0,//是否能領代金券 "dis_money":[2,4]//返回的代金券(多張) }, "shop_return_price": { "code":0,//是否返券 "min_price":20,//返券起始價格 "dis_money":4//商家返券數 }, "shop_return_invoice": { "code":0,//是否開發票 "min_price":0,//開票起始價格 }, }, { "id": 1001,//id "type":0,//1表明新店、2表明品牌店、0表明都不是 "name": "叫了個炸雞(鼓樓店)",//店名 "delivery_type": 1,//1表明美團專送,0表明不是 "pic_url": "http://p0.meituan.net/0.84.63/xianfu/00b9386a556a39010186a609ce9289e370566.jpg",//圖片地址 "avg_delivery_time": 30,//平均送達時間 "delivery_distance": 2502,//平均送達距離(單位爲米,超過一公里要轉化成公里) "min_price": 20,//起送價 "delivery_price": 3,//配送費 "wm_poi_score": 4.2,//評分 "month_sale_num": 3857,//月售 "shop_discount": { "code":1,//是否能領代金券 "dis_money":[1,5,10]//返回的代金券(多張) }, "shop_return_price": { "code":0,//是否返券 "min_price":20,//返券起始價格 "dis_money":1//商家返券數 }, "shop_return_invoice": { "code":0,//是否開發票 "min_price":0,//開票起始價格 }, }, { "id": 1002,//id "type":2,//1表明新店、2表明品牌店、0表明都不是 "name": "望湘園(南京國際廣場店)",//店名 "delivery_type": 0,//1表明美團專送,0表明不是 "pic_url": "http://p1.meituan.net/0.84.63/xianfu/2d91e93c70f91696907f040392c4835f13918.jpg",//圖片地址 "avg_delivery_time": 30,//平均送達時間 "delivery_distance": 889,//平均送達距離(單位爲米,超過一公里要轉化成公里) "min_price": 20,//起送價 "delivery_price": 3.5,//配送費 "wm_poi_score": 4.7,//評分 "month_sale_num": 1435,//月售 "shop_discount": { "code":0,//是否能領代金券 "dis_money":[2,4]//返回的代金券(多張) }, "shop_return_price": { "code":0,//是否返券 "min_price":20,//返券起始價格 "dis_money":4//商家返券數 }, "shop_return_invoice": { "code":1,//是否開發票 "min_price":0,//開票起始價格 }, } ]
index.vue <!-- 周邊商鋪 --> <div class="nearby"> <shop-list-item v-for="item in shopList" :item= "item"></shop-list-item> </div> shop-list-item.vue <div class="seller-list-item" > <div class="left"> <span :class="{pingpai:item.type===2,xindian:item.type===1,hide:item.type===0}">{{item.type===1?"新店":"品牌"}}</span> <img :src="item.pic_url"> </div> </div>
<div class="seller-list-item" > <div class="left"> <span :class="{pingpai:item.type===2,xindian:item.type===1,hide:item.type===0}">{{item.type===1?"新店":"品牌"}}</span> <img :src="item.pic_url"> </div> <div class="content"> <div class="name">{{item.name}}</div> <div class="mid"> <span class="fl">* * * * *</span> <span class="count fl">月售{{ item.month_sale_num }}</span> <span class="distance fr">{{ distance }}</span> <span class="time fr">{{ item.avg_delivery_time }}分鐘 |</span> </div> <div class="down"> <span >起送 {{ item.min_price }} |</span> <span >配送 {{ item.delivery_price }} |</span> <!-- 數據中忘了平均消費價格,這裏直接用起送價格數據代替 --> <span >人均 {{ item.min_price + 6 }}</span> <div class="zhuansong" v-show="item.delivery_type === 1"> <span >美團專送</span> </div> </div> <ul class="activety"> <li class="jian" v-show="item.shop_discount.code"><img src="./jian.png" ><span>{{replacePrice}}</span></li> <li class="fan" v-show="item.shop_return_price.code"><img src="./fan.png" ><span>{{"實際支付" + item.shop_return_price.min_price + "元返" + item.shop_return_price.dis_money +"元商家代金券"}}</span></li> <li class="fapiao" v-show="item.shop_return_invoice.code"><img src="./piao.png" ><span>{{"本店支持開發票,開票金額" + item.shop_return_invoice.min_price + "元起"}}</span></li> </ul> </div> </div>
methods: { findMaxAndMin(arr) { var min = arr[0] var max = arr[0] for (var i = 0; i < arr.length; i++) { if (arr[i] > max) { max = arr[i] } if (arr[i] < min) { min = arr[i] } } return {max,min} } }, computed: { // 距離km、m換算 distance() { if (this.item.delivery_distance > 1000) { return (this.item.delivery_distance / 1000.0).toFixed(1) + 'km' }else { return this.item.delivery_distance + 'm' } }, // 代金券分一張和多張 replacePrice () { if (this.item.shop_discount.dis_money.length === 1) { return "可領" + this.item.shop_discount.dis_money[0] +"元代金券" }else { let {max,min} = this.findMaxAndMin(this.item.shop_discount.dis_money) return "可領" + min + "~" + max +"元代金券" } } },
.seller-list-item { margin-bottom: 5px; display: flex; flex-direction: row; padding: 12.5px 0 12.5px 0; overflow: hidden; margin-left:10px; border-bottom: solid 1px #eee; } /*左側圖片*/ .left { position: relative; flex: 0 0 86px; width: 86px; } .left span { display: inline-block; text-align: center; position: absolute; left: 0; top: 0; width: 28px; height: 14px; line-height: 14px; font-size: 12px; color: white; } span.hide { display: none; } span.pingpai { background-color: #ffa627; } span.xindian { background-color: #21c56c; } .left img { border:solid 1px #e4e4e4; display: block; width: 84px; height: 63px; margin: 0 auto; } /*右側內容*/ .content { /*background-color: red;*/ flex: 1; display: flex; flex-direction: column; padding: 0 15px 0 10px; } .content .name { font-size: 17px; color: #333; overflow: hidden; font-weight: bold; overflow: hidden; } /*月售、送達時間、距離*/ .content .mid { flex: 1; margin-top: 7px; color: #666; font-size: 12px; } .mid .count { margin-left: 10px; } .mid .distance { margin-left: 5px; margin-top: 2px; } .mid .time { } /*起送配送人均*/ .down { flex: 1; margin-top: 7px; font-size: 13px; color: #656565; } .down .zhuansong { float: right; font-size: 13px; background-color: #ffd161; color: #333; } .zhuansong span { height: 15px; line-height: 15px; padding: 0 6px; display: inline-block; position: relative; } .zhuansong span::before, .zhuansong span::after { content: ''; position: absolute; border: 3px solid #fff; width: 0; height: 0; font-size: 0; } .zhuansong span::before { left: 0; top: 0; border-color: #fff #ffd161 #ffd161 #fff; } .zhuansong span::after { right: 0; bottom: 0; border-color: #ffd161 #fff #fff #ffd161; } /*活動*/ .activety { flex: 1; margin-top: 7px; color: #898989; font-size: 12px; text-align: left; } .activety li { height: 17px; margin-bottom: 4px; } .activety li img { width: 14px; height: 14px; vertical-align: middle; } .activety li span { vertical-align: middle; margin-left: 6px; }
把星星分爲全星、半星、和無星星三種,好比3.7分就是3個全星星、1個半星星、一個無星星
<div> <i class="starItem" :class="{half:(score<1 && score> 0),zero:(score <= 0)}"></i> <i class="starItem" :class="{half:(score<2 && score> 1),zero:(score <= 1)}"></i> <i class="starItem" :class="{half:(score<3 && score> 2),zero:(score <= 2)}"></i> <i class="starItem" :class="{half:(score<4 && score> 3),zero:(score <= 3)}"></i> <i class="starItem" :class="{half:(score<5 && score> 4),zero:(score <= 4)}"></i> </div> .starItem { background: url(./star.png) no-repeat; background-size: cover; width: 10px; height: 10px; float: left; margin-right: 4px; background-position: 0 0; } .half { background-position: -14px 0; } .zero { background-position: -28px 0; }
新版vue-cli關閉了自動啓動瀏覽器,能夠經過吧build/config/index.js 中大概第18行的 autoOpenBrowser: false,改成true,而後從新啓動npm run dev ,就能自動打開瀏覽器了
在webpack.dev.conf.js 中加入代碼返回數據,webpack3內置了express,before方法的參數app就是express的實例對象
before(app) { var shops = require('../mock/shop.json') app.get('/api/shops', function(req, res) { res.json({ code: 0, data: shops }); }); }
安裝axios,在main.js中引入axios
cnpm i axios --save
webpack
import axios from 'axios' Vue.prototype.axios = axios
在index.vue中獲取數據
this.axios.get('/api/shops',{ params: { } }).then(res =>{ if (res.data.code === 0) { this.shopList = res.data.data } }).catch(error => { console.log(error) })