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

初識小程序,爲它的小巧玲瓏所吸引,不禁得心血來潮。這不正是用戶所須要的嗎?既方便快捷,又不佔手機內存。因此我下定決心必定要作出一個本身的小程序,而後賺錢、賺錢、賺錢...固然如今只是學習階段,因此先仿一個高端產品來挑戰自我吧。說到高端,天然然而的就想到了美團。以後噼裏啪啦一頓忙乎,終於作出了一點樣子來,但願能爲同爲小白的同窗們提供一點幫助和參考,如今咱們進入正題。前端

開發工具git

微信web開發者工具: 官網就能夠下載,相信你們早就安裝好了吧。 
小程序 API: 官網提供的文檔,不懂得地方多看兩遍基本上就能夠解決了。 
Easy Mock: 一個可以提供虛擬數據接口的網站,在前端獨自開發的狀況下,實在是再好不過的工具了。 
功能github

已經實現的功能:web

主界面 
訂單界面 
用戶界面 
點菜界面 
定位界面 
未實現的功能:json

數都數不清,畢竟大企業的產品,不是說模仿就模仿的,因此只實現了一些主要的功能,和一些能力以內的功能... 
項目啓動小程序

建立界面api

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中配置,其餘頁面的標題欄都以此爲例。app

 

添加底欄

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.<swiper class="categoryList" indicator-dots="true" 
 2.indicator-color="rgba(228,228,228,1)" 
 3.indicator-active-color="#FECA49">
 4.<block wx:for="{{categoryList}}" wx:key="">
 5.<swiper-item>
 6.<block wx:for="{{item}}" wx:key="">
 7.<view class="category-info">
 8.<image src="{{item.src}}" 
 9.class="category-image"></image>
 10.<view class="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.<view class="mask"
 2.hidden="{{mask2Hidden}}" bindtap="mask2Cancel">
 3.<template is="sort_list" data="{{selected,sortSelected}}"/>
 4.<scroll-view class="filterList" scroll-y="true" >
 5.<view class="filterList-characteristic-title">商家特點</view>
 6.<view class="filterList-characteristic-items">
 7.<block wx:for="{{characteristicList}}" wx:key="">
 8.<view class="filterList-characteristic-item {{characteristicSelected[index]==true?'characteristic-selected':''}}"
 9.catchtap="characteristicSelected" data-index="{{index}}">{{item.text}}</view>
 10.</block>
 11.</view>
 12.<view class="filterList-discount-title">優惠活動(單選)</view>
 13.<view class="filterList-discount-items">
 14.<block wx:for="{{discountList}}" wx:key="">
 15.<view class="filterList-discount-item {{discountSelected==index?'discount-selected':''}}"
 16.catchtap="discountSelected" data-index="{{index}}">
 17.<text class="filterList-discount-item-icon"
 18.style="background:{{item.iconColor}}">{{item.icon}}</text>
 19.{{item.text}}</view>
 20.</block>
 21.</view>
 22.</scroll-view>
 23.<view class="filterList-footer">
 24.<view class="filterList-footer-delect"
 25.catchtap="clearSelectedNumb">清除篩選</view>
 26.<view class="filterList-footer-finish" bindtap="finish">完成 
 27.<view class="filterList-footer-finish-number" hidden="{{selectedNumb==0}}">{{selectedNumb}}
 28.</view>
 29.</view>
 30.</view>
 31.</view>

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

定位界面

先上效果圖:

image

頁面結構:

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

這個界面主要涉及到的就是彈出層和百度地圖API的調用,調用方法能夠查看百度地圖API,具體點擊事件代碼以下:

 27.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.})this.search(e.detail.value);
 28.}else{
 29.this.setData({
 30.hidden: true
 31.})
 32.}
 33.},
 34.search: function (text){
 35.var that = this;
 36.wx.request({
 37.url: 'http://api.map.baidu.com/place/v2/search?query=' + text +'&page_size=20&page_num=0&scope=2&region=南昌&output=json&ak=btsVVWf0TM1zUBEbzFz6QqWF',
 38.success: function(res){
 39.console.log(res);
 40.that.setData({
 41.locationList:res.data.results
 42.})
 43.} 
 44.})
 45.},

點菜界面 
效果圖以下:

image

頁面結構以下:

1.<import src = "../common/orderPage.wxml"/>
 2.<import src = "../common/commentPage.wxml"/>
 3.<view class="container" disable-scroll="true">
 4.<view class="header">
 5.<block wx:for="{{swiperTitle}}" wx:key="">
 5.<view class="title {{index==currentPage?'selected':''}}" data-index="{{index}}
 6.bindtap="turnPage">{{item.text}}</view>
 7.</block> 
 8.</view>
 9.<swiper class="swiper" current="{{currentPage}} 
 10.bindchange="turnTitle">
 11.<swiper-item id="orderPage">
 12.<template is="orderPage" data="{{menu,selected,howMuch,cost,pullBar}}"/>
 13.</swiper-item>
 14.<swiper-item id="commentPage">
 15.<template is="commentPage" data="{{categoryList}}"/>
 16.</swiper-item>
 17.<swiper-item id="restaurantPage"></swiper-item>
 18.</swiper> 
 19.</view>

菜單頁面以下:<template name="orderPage">

    2.<scroll-view class="orderPage-sideBar"

     3.bindscrolltolower="lower"

  1. scroll-y="true">
  2. <block wx:for="{{menu}}" wx:key="">
  3. <view class="menuList">
  4. <view class="menu {{index==selected?'selected':''}}"
  5. data-index="{{index}}"
  6. catchtap="turnMenu">{{item.typeName}}</view>
  7. </view>
  8. </block>
  9. </scroll-view>
  10. <scroll-view class="foodList" scroll-y="true">
  11. <view class="title">{{menu[selected].typeName}}</view>
  12. <block wx:for="{{menu[selected].menuContent}}" wx:key="">
  13. <view class="food">
  14. <image class="img" src="{{item.src}}"></image>
  15. <view class="food-info">
  16. <view class="name">{{item.name}}</view>
  17. <view class="sales">月售 {{item.sales}} 贊 {{item.rating}}
  18. </view>
  19. <view class="price">¥ {{item.price}}</view>
  20. </view>
  21. <view class="food-numb">
  22. <view class="remove"
  23. bindtap="removeFromTrolley"
  24. hidden="{{item.numb==0}}"
  25. data-index="{{index}}">-</view>
  26. <text class="text"
  27. hidden="{{item.numb==0}}">{{item.numb}}</text>
  28. <view class="add"
  29. bindtap="addToTrolley" data-index="{{index}}">+</view>
  30. </view>
  31. </view>
  32. </block>
  33. </scroll-view>
  34. <view class="footer {{cost!=0?'active':''}}">
  35. <view class="howMuch">
  36. <view class="img" style="background:{{cost!=0?'#FFD161':'#E7E7E7'}};">
  37. <image src="/pages/images/trolley.png" style="width:60rpx;height:60rpx;"></image>
  38. </view>
  39. <view class="cost" hidden="{{cost==0}}">¥{{cost}}</view>
  40. <view class="free">免配送費</view>
  41. </view>
  42. <view class="pay">{{cost!=0?'去結算':'15元起送'}}</view>
  43. </view>
  44. </template>

tab切換

這個界面最主要的功能就是tab切換,和點菜功能。其中tab切換其實用的仍是swiper,由於swiper有一個current屬性表示的是swiper當下顯示的頁面的序號,只須要將tab中被激活的項與swiper的頁面互相綁定就能夠了,具體代碼以下:

1.turnPage: function (e) {
 2.this.setData({
 3.currentPage: e.currentTarget.dataset.index
 4.})
 5.},
 6.turnTitle: function (e) {
 7.if(e.detail.source=="touch"){//判斷是不是滑動引發的界面切換
 8.this.setData({
 9.currentPage: e.detail.current
 10.})
 11.}
 12.},

當點擊title中的項時獲取當前序號,再將它賦值給current,當手指滑動swiper時觸發bindchange事件,獲取當前頁面序號,使相應序號的title處於被選中的狀態。有一個值得注意的地方是當點擊title中的項時也會觸發swiper的bindchange事件,可是咱們只想讓它在滑動swiper時觸發,不然就會出現setData過於頻繁的警告,因此咱們須要在turnTitle中加一段判斷語句,判斷頁面滑動的緣由是否爲滑動,若是不是則不執行下面的語句。 
點菜功能只是數據綁定界面的更加複雜的應用,並且還有許多不妥之處,這裏就不做說明了,有興趣的朋友能夠去個人GitHub看詳細的代碼。

總結

此次項目是本人的第一個微信小程序項目,但願能給你們提供一些參考價值,有什麼問題和想說的均可以在評論區告訴我,文章和代碼中諸多不穩當的地方也勞煩各位不吝言辭,多多斧正。這樣才能幫助我更快的進步,感謝!

項目地址:https://github.com/tzc123/wx_project_meituan

相關文章
相關標籤/搜索