初識小程序,為它的小巧玲瓏所吸引,不由得心血來潮。這不正是用戶所需要的嗎?既方便快捷,又不占手機內(nèi)存。所以我下定決心一定要做出一個自己的小程序,然后賺錢、賺錢、賺錢...當(dāng)然現(xiàn)在只是學(xué)習(xí)階段,所以先仿一個高端產(chǎn)品來挑戰(zhàn)自我吧。說到高端,自然然而的就想到了美團。之后噼里啪啦一頓忙乎,終于做出了一點樣子來,希望能為同為小白的同學(xué)們提供一點幫助和參考,現(xiàn)在我們進入正題。
開發(fā)工具
微信web開發(fā)者工具: 官網(wǎng)就可以下載,相信大家早就安裝好了吧。 小程序 API: 官網(wǎng)提供的文檔,不懂得地方多看兩遍基本上就可以解決了。 Easy Mock: 一個能夠提供虛擬數(shù)據(jù)接口的網(wǎng)站,在前端獨自開發(fā)的情況下,實在是再好不過的工具了。 功能
已經(jīng)實現(xiàn)的功能:
主界面 訂單界面 用戶界面 點菜界面 定位界面 未實現(xiàn)的功能:
數(shù)都數(shù)不清,畢竟大企業(yè)的產(chǎn)品,不是說模仿就模仿的,所以只實現(xiàn)了一些主要的功能,和一些能力之內(nèi)的功能... 項目啟動
創(chuàng)建界面
"pages":[
"pages/home/home",
"pages/menu/menu",
"pages/location/location",
"pages/my/my",
"pages/order/order"
.],
只要編輯app.js中的pages屬性,就會在項目目錄下的pages文件夾里自動生成一個文件夾,里面包擴了.wxml 、 .wxss 、 .json 、 .js這樣四個文件。wxml就是界面結(jié)構(gòu)文件, .wxss就是樣式文件, .js是用來存放js代碼并實現(xiàn)界面邏輯的地方,至于 .json就是用來配置頁面屬性的地方,如:修改標(biāo)題欄的顏色,和文字。
配置標(biāo)題欄的樣式
"window":{
"navigationBarTitleText": "美團外賣+",
"navigationBarTextStyle": "white",
"navigationBarBackgroundColor": "#FFC640"
},
同樣是在app.json中配置,其他頁面的標(biāo)題欄都以此為例。
添加底欄
"tabBar": {
"color": "#272636",
"selectedColor": "#FFD161",
"backgroundColor": "#fff",
"borderStyle": "#a8a8a8",
"list": [
{
"pagePath": "pages/home/home",
"iconPath": "pages/images/home.png",
"selectedIconPath": "pages/images/home-selected.png",
"color":"white",
"text": "首頁"
},
{
"pagePath": "pages/order/order",
"iconPath": "pages/images/order.png",
"selectedIconPath": "pages/images/order-selected.png",
"text": "訂單"
},
{
"pagePath": "pages/my/my",
"iconPath": "pages/images/my.png",
"selectedIconPath": "pages/images/my-selected.png",
"text": "我的"
}
]
}
在app.json中編寫以上代碼,這是小程序自帶的功能,只需要照搬照抄就可以了,極其方便,效果如下:
image 數(shù)據(jù)請求
/**
* 生命周期函數(shù)--監(jiān)聽頁面顯示
*/
onShow: function () {
var that = this;
wx.request({
url: "https://www.easy-mock.com/mock/596257bc9adc231f357c4664/restaurant/info",//easy-mock生成的虛擬數(shù)據(jù)接口鏈接
method: "GET",
success: function (res) {//成功得到數(shù)據(jù),對數(shù)據(jù)進行處理
that.setData({//將數(shù)據(jù)發(fā)送到data中
restaurant: res.data.data.restaurant,
location: wx.getStorageSync('location')
})
}
});
},
data是每個頁面.js文件中都存在的一個鍵,用來儲存本頁面需要用到的數(shù)據(jù)。具體使用,可在wxml文件中用{{'data中的鍵名'}}的形式調(diào)用數(shù)據(jù)。 虛擬數(shù)據(jù)大致如下:
{
"success": true,
"data": {
"restaurant": [{
"name": "御膳房",
"src": "http://i2.kiimg.com/601998/a955867016875a41.jpg",
"star": 4.5,
"sales": 641,
"initial_price": 0,
"distribution_price": 0,
"distance": "156m",
"time": 33
}, {
"name": "韓式炸雞啤酒屋",
"star": 4.5,
"sales": 731,
"src": "http://i4.piimg.com/601998/9ce47f2f19d7717d.jpg",
"initial_price": 15,
"distribution_price": 0,
"distance": "1.3km",
"time": 52
},{
//略去
},{
//略去
},{
//...
}]
}
}
主界面 效果圖:
image swiper控件應(yīng)用
首先是兩頁標(biāo)簽的滑動切換,這里使用的是swiper,它是一款小程序自帶的滑塊組件,使用掌握起來非常簡單,具體代碼如下:
<swiper class="categoryList" indicator-dots="true"
indicator-color="rgba(228,228,228,1)"
indicator-active-color="#FECA49">
<block wx:for="{{categoryList}}" wx:key="">
<swiper-item>
<block wx:for="{{item}}" wx:key="">
<view class="category-info">
<image src="{{item.src}}"
class="category-image"></image>
<view class="category-text">{{item.name}}</view>
</view>
</block>
</swiper-item>
</block>
</swiper>
swiper標(biāo)簽就是滑塊組件的主體,表示可以滑動的區(qū)域,其中indicator-dots屬性是設(shè)置設(shè)置點是否顯示。接下來swiper-item標(biāo)簽在swiper之中表示的是每一個用來作為滑動的頁面。這里用包裹著swiper-item表示的是使用categoryList對象數(shù)組中數(shù)據(jù)來循環(huán)渲染swiper-item,swiper-item的數(shù)量取決于categoryList中有多少組數(shù)據(jù)。之后在swiper-item中的block標(biāo)簽表示的是在一個頁面中用categoryList.item中的數(shù)據(jù)循環(huán)渲染多個類似的標(biāo)簽,這些標(biāo)簽就是效果圖中的類別項,總共兩頁,每頁八個。這就是swiper和循環(huán)渲染的一些基本用法。
彈出層的實現(xiàn)
<view class="mask"
hidden="{{mask2Hidden}}" bindtap="mask2Cancel">
<template is="sort_list" data="{{selected,sortSelected}}"/>
<scroll-view class="filterList" scroll-y="true" >
<view class="filterList-characteristic-title">商家特色</view>
<view class="filterList-characteristic-items">
<block wx:for="{{characteristicList}}" wx:key="">
<view class="filterList-characteristic-item {{characteristicSelected[index]==true?'characteristic-selected':''}}"
catchtap="characteristicSelected" data-index="{{index}}">{{item.text}}</view>
</block>
</view>
<view class="filterList-discount-title">優(yōu)惠活動(單選)</view>
<view class="filterList-discount-items">
<block wx:for="{{discountList}}" wx:key="">
<view class="filterList-discount-item {{discountSelected==index?'discount-selected':''}}"
catchtap="discountSelected" data-index="{{index}}">
<text class="filterList-discount-item-icon"
style="background:{{item.iconColor}}">{{item.icon}}</text>
{{item.text}}</view>
</block>
</view>
</scroll-view>
<view class="filterList-footer">
<view class="filterList-footer-delect"
catchtap="clearSelectedNumb">清除篩選</view>
<view class="filterList-footer-finish" bindtap="finish">完成
<view class="filterList-footer-finish-number" hidden="{{selectedNumb==0}}">{{selectedNumb}}
</view>
</view>
</view>
</view>
最外層的mask類的view就是一個遮罩層,用來覆蓋之前的界面形成遮罩的效果,并在上面顯示新的界面也就是彈出層。以上的代碼就是效果圖中點擊篩選按鈕所呈現(xiàn)出來的內(nèi)容了。其中bindtap屬性就是點擊事件的綁定了,具體的點擊事件需要在.js文件中設(shè)置。值得一提的是,bindtap事件是會把當(dāng)前標(biāo)簽受到的點擊冒泡給它的父容器,這就相當(dāng)與同時點擊了他的父容器,如果想阻止冒泡的話就需要使用catchtap。
定位界面
先上效果圖:
image
頁面結(jié)構(gòu):
<view class="header">
<view class="search-input">
<input placeholder="請輸入收貨地址"
bindinput="input"></input>
</view>
<view class="search-btn">搜索</view>
</view>
<view class="result-container" hidden="{{hidden}}">
<scroll-view scroll-y="true"class="search-result-list" hidden="{{hidden}}">
<block wx:for="{{locationList}}" wx:key="">
<view class="search-result" bindtap="onTap" data-key="{{item.address}}">{{item.name}}
<view class="search-result-desc">{{item.address}}</view>
</view>
</block>
</scroll-view>
</view>
<view class="getLocation"
bindtap="getLocation">點擊定位當(dāng)前位置</view>
<view class="addLocation">新增收貨地址
<view class="addLocation-icon">+</view>
</view>
<view class="myLocation">我的收貨地址</view>
<view class="LocatonInfo"></view>
<view class="userTel"></view>
這個界面主要涉及到的就是彈出層和百度地圖API的調(diào)用,調(diào)用方法可以查看百度地圖API,具體點擊事件代碼如下:
getLocation: function () { wx.getLocation({ type: 'gcj02', success: function (res) { var latitude = res.latitude var longitude = res.longitude wx.request({ url: 'http://api.map.baidu.com/geocoder/v2/?ak=btsVVWf0TM1zUBEbzFz6QqWF&coordtype=gcj02ll&location=' + latitude + ',' + longitude + '&output=json&pois=0', method: "get", success: function (res) { console.log(res.data.result.formatted_address) wx.setStorageSync('location', res.data.result.formatted_address.substr(res.data.result.formatted_address.indexOf('市') + 1, 10)) } }) } }) wx.switchTab({ url: '/pages/home/home' }) }, input: function (e){ if(e.detail.value){ this.setData({ hidden: false })
this.search(e.detail.value); }else{ this.setData({ hidden: true }) } }, search: function (text){ var that = this; wx.request({ url: 'http://api.map.baidu.com/place/v2/search?query=' + text +'&page_size=20&page_num=0&scope=2®ion=南昌&output=json&ak=btsVVWf0TM1zUBEbzFz6QqWF', success: function(res){ console.log(res); that.setData({ locationList:res.data.results }) } }) },
點菜界面 效果圖如下:
image
頁面結(jié)構(gòu)如下:
<import src = "../common/orderPage.wxml"/>
<import src = "../common/commentPage.wxml"/>
<view class="container" disable-scroll="true">
<view class="header">
<block wx:for="{{swiperTitle}}" wx:key="">
<view class="title {{index==currentPage?'selected':''}}" data-index="{{index}}
bindtap="turnPage">{{item.text}}</view>
</block>
</view>
<swiper class="swiper" current="{{currentPage}}
bindchange="turnTitle">
<swiper-item id="orderPage">
<template is="orderPage" data="{{menu,selected,howMuch,cost,pullBar}}"/>
</swiper-item>
<swiper-item id="commentPage">
<template is="commentPage" data="{{categoryList}}"/>
</swiper-item>
<swiper-item id="restaurantPage"></swiper-item>
</swiper>
</view>
菜單頁面如下:<template name="orderPage">
2.<scroll-view class="orderPage-sideBar"
3.bindscrolltolower="lower"
tab切換
這個界面最主要的功能就是tab切換,和點菜功能。其中tab切換其實用的還是swiper,因為swiper有一個current屬性表示的是swiper當(dāng)下顯示的頁面的序號,只需要將tab中被激活的項與swiper的頁面互相綁定就可以了,具體代碼如下:
turnPage: function (e) {
this.setData({
currentPage: e.currentTarget.dataset.index
})
},
turnTitle: function (e) {
if(e.detail.source=="touch"){//判斷是否是滑動引起的界面切換
this.setData({
currentPage: e.detail.current
})
}
},
當(dāng)點擊title中的項時獲取當(dāng)前序號,再將它賦值給current,當(dāng)手指滑動swiper時觸發(fā)bindchange事件,獲取當(dāng)前頁面序號,使相應(yīng)序號的title處于被選中的狀態(tài)。有一個值得注意的地方是當(dāng)點擊title中的項時也會觸發(fā)swiper的bindchange事件,但是我們只想讓它在滑動swiper時觸發(fā),否則就會出現(xiàn)setData過于頻繁的警告,所以我們需要在turnTitle中加一段判斷語句,判斷頁面滑動的原因是否為滑動,如果不是則不執(zhí)行下面的語句。 點菜功能只是數(shù)據(jù)綁定界面的更加復(fù)雜的應(yīng)用,而且還有許多不妥之處,這里就不作說明了,有興趣的朋友可以去我的GitHub看詳細(xì)的代碼。
總結(jié)
這次項目是本人的第一個微信小程序項目,希望能給大家提供一些參考價值,有什么問題和想說的都可以在評論區(qū)告訴我,文章和代碼中諸多不妥當(dāng)?shù)牡胤揭矂跓└魑徊涣哐赞o,多多斧正。這樣才能幫助我更快的進步,感謝!
項目地址:https://github.com/tzc123/wx_project_meituan
工作日 8:30-12:00 14:30-18:00
周六及部分節(jié)假日提供值班服務(wù)