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