1. 程式人生 > >微信小程式(初學篇)——仿美團外賣

微信小程式(初學篇)——仿美團外賣

初識小程式,為它的小巧玲瓏所吸引,不由得心血來潮。這不正是使用者所需要的嗎?既方便快捷,又不佔手機記憶體。所以我下定決心一定要做出一個自己的小程式,然後賺錢、賺錢、賺錢...當然現在只是學習階段,所以先仿一個高階產品來挑戰自我吧。說到高階,自然然而的就想到了美團。之後噼裡啪啦一頓忙乎,終於做出了一點樣子來,希望能為同為小白的同學們提供一點幫助和參考,現在我們進入正題。

開發工具

微信web開發者工具: 官網就可以下載,相信大家早就安裝好了吧。 
小程式 API: 官網提供的文件,不懂得地方多看兩遍基本上就可以解決了。 
Easy Mock: 一個能夠提供虛擬資料介面的網站,在前端獨自開發的情況下,實在是再好不過的工具了。 
功能

已經實現的功能:

主介面 
訂單介面 
使用者介面 
點菜介面 
定位介面 
未實現的功能:

數都數不清,畢竟大企業的產品,不是說模仿就模仿的,所以只實現了一些主要的功能,和一些能力之內的功能... 
專案啟動

建立介面

1."pages":[
 2."pages/home/home",
 3."pages/menu/menu",
 4."pages/location/location",
 5."pages/my/my",
 6."pages/order/order"
 7.],

只要編輯app.js中的pages屬性,就會在專案目錄下的pages資料夾裡自動生成一個資料夾,裡面包擴了.wxml 、 .wxss 、 .json 、 .js這樣四個檔案。wxml就是介面結構檔案, .wxss就是樣式檔案, .js是用來存放js程式碼並實現介面邏輯的地方,至於 .json就是用來配置頁面屬性的地方,如:修改標題欄的顏色,和文字。

配置標題欄的樣式

1."window":{
 2."navigationBarTitleText": "美團外賣+",
 3."navigationBarTextStyle": "white",
 4."navigationBarBackgroundColor": "#FFC640"
 5.},

同樣是在app.json中配置,其他頁面的標題欄都以此為例。

新增底欄

1."tabBar": {
 2."color": "#272636",
 3."selectedColor": "#FFD161",
 4."backgroundColor": "#fff",
 5."borderStyle"
: "#a8a8a8",  6."list": [  7.{  8."pagePath": "pages/home/home",  9."iconPath": "pages/images/home.png",  10."selectedIconPath": "pages/images/home-selected.png",  11."color":"white",  12."text": "首頁"  13.},  14.{  15."pagePath": "pages/order/order",  16."iconPath": "pages/images/order.png",  17."selectedIconPath": "pages/images/order-selected.png",  18."text": "訂單"  19.},  20.{  21."pagePath": "pages/my/my",  22."iconPath": "pages/images/my.png",  23."selectedIconPath": "pages/images/my-selected.png",  24."text": "我的"  25.}  26.]  27.}

在app.json中編寫以上程式碼,這是小程式自帶的功能,只需要照搬照抄就可以了,極其方便,效果如下:

image 
資料請求

1./**
 2.* 生命週期函式--監聽頁面顯示
 3.*/
 4.onShow: function(){
 5.var that = this;
 6.wx.request({
 7.url: "https://www.easy-mock.com/mock/596257bc9adc231f357c4664/restaurant/info",//easy-mock生成的虛擬資料介面連結
 8.method: "GET",
 9.success: function(res){//成功得到資料,對資料進行處理
 10.that.setData({//將資料傳送到data中
 11.restaurant: res.data.data.restaurant,
 12.location: wx.getStorageSync('location')
 13.})
 14.}
 15.});
 16.},

data是每個頁面.js檔案中都存在的一個鍵,用來儲存本頁面需要用到的資料。具體使用,可在wxml檔案中用{{'data中的鍵名'}}的形式呼叫資料。 
虛擬資料大致如下:

1.{
 2."success": true,
 3."data": {
 4."restaurant": [{
 5."name": "御膳房", 
 6."src": "http://i2.kiimg.com/601998/a955867016875a41.jpg",
 7."star": 4.5,
 8."sales": 641,
 9."initial_price": 0,
 10."distribution_price": 0,
 11."distance": "156m",
 12."time": 33
 13.}, {
 14."name": "韓式炸雞啤酒屋", 
 15."star": 4.5,
 16."sales": 731,
 17."src": "http://i4.piimg.com/601998/9ce47f2f19d7717d.jpg",
 18."initial_price": 15,
 19."distribution_price": 0,
 20."distance": "1.3km",
 21."time": 52
 22.},{
 23.//略去
 24.},{
 25.//略去
 26.},{
 27.//...
 28.}]
 29.}
 30.}

主介面 
效果圖:

image 
swiper控制元件應用

首先是兩頁標籤的滑動切換,這裡使用的是swiper,它是一款小程式自帶的滑塊元件,使用掌握起來非常簡單,具體程式碼如下:

1.<swiperclass="categoryList"indicator-dots="true"2.indicator-color="rgba(228,228,228,1)"3.indicator-active-color="#FECA49">
 4.<blockwx:for="{{categoryList}}"wx:key="">
 5.<swiper-item>
 6.<blockwx:for="{{item}}"wx:key="">
 7.<viewclass="category-info">
 8.<imagesrc="{{item.src}}"9.class="category-image"></image>
 10.<viewclass="category-text">{{item.name}}</view>
 11.</view>
 12.</block>
 13.</swiper-item>
 14.</block>
 15.</swiper>

swiper標籤就是滑塊元件的主體,表示可以滑動的區域,其中indicator-dots屬性是設定設定點是否顯示。接下來swiper-item標籤在swiper之中表示的是每一個用來作為滑動的頁面。這裡用包裹著swiper-item表示的是使用categoryList物件陣列中資料來迴圈渲染swiper-item,swiper-item的數量取決於categoryList中有多少組資料。之後在swiper-item中的block標籤表示的是在一個頁面中用categoryList.item中的資料迴圈渲染多個類似的標籤,這些標籤就是效果圖中的類別項,總共兩頁,每頁八個。這就是swiper和迴圈渲染的一些基本用法。

彈出層的實現

1.<viewclass="mask"2.hidden="{{mask2Hidden}}"bindtap="mask2Cancel">
 3.<templateis="sort_list"data="{{selected,sortSelected}}"/>
 4.<scroll-viewclass="filterList"scroll-y="true" >
 5.<viewclass="filterList-characteristic-title">商家特色</view>
 6.<viewclass="filterList-characteristic-items">
 7.<blockwx:for="{{characteristicList}}"wx:key="">
 8.<viewclass="filterList-characteristic-item {{characteristicSelected[index]==true?'characteristic-selected':''}}"9.catchtap="characteristicSelected"data-index="{{index}}">{{item.text}}</view>
 10.</block>
 11.</view>
 12.<viewclass="filterList-discount-title">優惠活動(單選)</view>
 13.<viewclass="filterList-discount-items">
 14.<blockwx:for="{{discountList}}"wx:key="">
 15.<viewclass="filterList-discount-item {{discountSelected==index?'discount-selected':''}}"16.catchtap="discountSelected"data-index="{{index}}">
 17.<textclass="filterList-discount-item-icon"18.style="background:{{item.iconColor}}">{{item.icon}}</text>
 19.{{item.text}}</view>
 20.</block>
 21.</view>
 22.</scroll-view>
 23.<viewclass="filterList-footer">
 24.<viewclass="filterList-footer-delect"25.catchtap="clearSelectedNumb">清除篩選</view>
 26.<viewclass="filterList-footer-finish"bindtap="finish">完成 
 27.<viewclass="filterList-footer-finish-number"hidden="{{selectedNumb==0}}">{{selectedNumb}}
 28.</view>
 29.</view>
 30.</view>
 31.</view>

最外層的mask類的view就是一個遮罩層,用來覆蓋之前的介面形成遮罩的效果,並在上面顯示新的介面也就是彈出層。以上的程式碼就是效果圖中點選篩選按鈕所呈現出來的內容了。其中bindtap屬性就是點選事件的綁定了,具體的點選事件需要在.js檔案中設定。值得一提的是,bindtap事件是會把當前標籤受到的點選冒泡給它的父容器,這就相當與同時點選了他的父容器,如果想阻止冒泡的話就需要使用catchtap。

定位介面

先上效果圖:

image

頁面結構:

1.<viewclass="header">
 2.<viewclass="search-input">
 3.<inputplaceholder="請輸入收貨地址"4.bindinput="input"></input>
 5.</view>
 6.<viewclass="search-btn">搜尋</view>
 7.</view>
 8.<viewclass="result-container"hidden="{{hidden}}">
 9.<scroll-viewscroll-y="true"class="search-result-list"hidden="{{hidden}}">
 10.<blockwx:for="{{locationList}}"wx:key="">
 11.<viewclass="search-result"bindtap="onTap"data-key="{{item.address}}">{{item.name}}
 12.<viewclass="search-result-desc">{{item.address}}</view> 
 13.</view>
 14.</block>
 15.</scroll-view>
 16.</view>
 17.<viewclass="getLocation"18.bindtap="getLocation">點選定位當前位置</view>
 19.<viewclass="addLocation">新增收貨地址
 20.<viewclass="addLocation-icon">+</view>
 21.</view>
 22.<viewclass="myLocation">我的收貨地址</view>
 23.<viewclass="LocatonInfo"></view>
 24.<viewclass="userTel"></view>

這個介面主要涉及到的就是彈出層和百度地圖API的呼叫,呼叫方法可以檢視百度地圖API,具體點選事件程式碼如下:

1.getLocation: function () {
 2.wx.getLocation({
 3.type: 'gcj02',
 4.success: function (res) {
 5.var latitude = res.latitude
 6.var longitude = res.longitude
 7.wx.request({
 8.url: 'http://api.map.baidu.com/geocoder/v2/?ak=btsVVWf0TM1zUBEbzFz6QqWF&coordtype=gcj02ll&location=' + latitude + ',' + longitude + '&output=json&pois=0',
 9.method: "get",
 10.success: function (res) {
 11.console.log(res.data.result.formatted_address)
 12.wx.setStorageSync('location', 
 13.res.data.result.formatted_address.substr(res.data.result.formatted_address.indexOf('市') + 1, 10))
 14.}
 15.})
 16.}
 17.})
 18.wx.switchTab({
 19.url: '/pages/home/home'
 20.})
 21.},
 22.input: function (e){
 23.if(e.detail.value){
 24.this.setData({
 25.hidden: false
 26.})
 27.this.search(e.detail.value);
 28.}else{
 29.this.setData({
 30.hidden: true
 31.})
 32.}
 33.},
 34.s