滴滴一夏, 小程式專車來了

hello等風來發表於2018-06-05

最近時常感嘆道:時間總是那麼的快,轉瞬即逝。對於像我這種剛入門的小生來講,技術每天都在更新,框架也層出不窮,有時候還沒弄懂這個知識大牛們又推出了更好的技術。當然學習好的技術也是十分重要的。但是在學習之後怎樣才能夠得到自己想要的呢,一個好的建議便是靜下心來寫點自己的東西,哪怕你完成不了也應該盡力去寫,老大曾講過要去實踐要去獨立思考,你才能掌握很多你看似懂了卻又很難處理的知識點。學習小程式的我已經過去了半個月了,前不久滴滴事件頗為轟動,於是便萌發了這篇文章,開啟滴滴的小程式。介面做了很大的變化,對於比較懷舊的我來說,還是挺喜歡以前的介面,於是決定打算自己手寫一個懷舊版滴滴小程式,接下來我會列舉我所遇到的坑和如何解決的方法,希望能夠幫到同樣在奮鬥的你...

前言

工欲善其事必先利其器,對於一個前端來說有一個好的工具能夠讓我們事半功倍。要想做好一個小程式我們首先也應該先選擇我們的兵器。

  • 利器1: 微信開發者工具
  • 利器2: VsCode集終端一起,方便我們後面Wepy、Mpvue小程式進階的學習,可謂非常的nice
  • 利器3: Easy Mock 使用這個網站我們可以快速的模擬出我們需要的資料,方便快捷。點這裡就可以看到我的資料了 資料介面

效果圖

說了一大堆,等於沒說,還是回到正題,先來一波動態圖。 這裡有更多的圖片等你

all

功能實現詳解

接下來我會對滴滴微信小程式主要功能,以及對應的資料介面和採用的元件/API技術,描述的詳細。讓我們離小程式更近一點,傳遞知識,分享收穫

功能一:首頁

首頁
功能描述:頂部導航的製作,點選相應的nav頁面呈現不同的內容,並且點選時能判斷是向前還是向後自動滑出下一個nav,實現動畫過度效果。輸入起始位置模擬等待的時間。 實現原理:

  • 模擬等待時間載入效果,使用元件化的概念,建立一個template資料夾
<template name="sprinner">
    <block wx:if="{{isLoading}}">
       <view class="spinner">
           <view class="bounce1"></view>
           <view class="bounce2"></view>
           <view class="bounce3"></view>
       </view>
    </block>
</template> 
複製程式碼

在需要用到載入效果的地方就可以直接使用,

 <import  src="/templates/sprinner.wxml" />
        <template is="sprinner" data='{{isLoading}}'>
        </template>
    //通過去設定isLoading的布林值來判斷是否需要顯示
複製程式碼
  • 頭部導航並且點選時能判斷滑出方向以及自動滑出,我們可以通過一個scroll-left="{{navScrollLeft}}"這個屬性去設定,點選nav我們可以動態的去改變這個值,從而達到這種效果。
  <scroll-view scroll-x="true" class="nav" scroll-left="{{navScrollLeft}}" scroll-with-animation="{{true}}">
        <block wx:for="{{navData}}" wx:for-index="id"  wx:for-item="navItem" wx:key="index">
            <view class="nav-item {{currentTab == id ?'active':''}}"  data-name="{{navItem.name}}" data-current="{{id}}" bindtap="switchNav">{{navItem.name}}</view>
        </block>        
    </scroll-view>
複製程式碼

怎樣去改變這個navScrollLeft的值呢?一開始想的是去設定一下nav的導航的left,然後超出則隱藏。坑啊,根本就實現不了。無法判斷左滑出還是又滑出,後來又想到設定一個閾值。累真的難寫。好像放棄啊,還是堅持下吧,於是想到分開來取寫他們的js

switchNav(e){
   var cur = e.currentTarget.dataset.current; 
        var singleNavWidth = this.data.windowWindth/4; //獲取螢幕寬度存放放四個nav,
        this.setData({
            navScrollLeft: (cur - 1) * singleNavWidth, //點選去減少每一個nav的值
            currentTab: cur,
        })  
 switchTab(e){
        var cur = event.detail.current;
        var singleNavWidth =55; //設定每一個nav的寬度
        this.setData({
            currentTab: cur,
            navScrollLeft: (cur - 1) * singleNavWidth //同樣動態的去改變這個值
        });
    },
複製程式碼

第一次打理這種頂部導航效果的小程式,而卻還帶一點特效的。以後的你如果碰到了就可以回來借鑑借鑑,避免跟我一樣,在這裡浪費大量的時間和精力了。我們可是要完成有效時間建立更大價值的程式猿呀...

功能二: 起始位置的選擇

為了做這個效果,反反覆覆的看了n遍文件,真的是比較坑爹。微信小程式api對於地圖這方面講的確實不怎麼詳細,可能是我這種對地圖處理天生迷茫的人。這裡將詳細的把我遇到的問題一一列舉出來,希望也能夠幫助到今後的你去處理地圖這種東西少踩點坑吧。

address
這裡使用到了關鍵詞搜尋,逆地址解析,地址解析,切換城市列表,建議以後做這個可以瞭解下騰訊地圖api,還是比較方便的

var QQMapWX = require('../../libs/qqmap-wx-jssdk.js');//匯入需要使用的包,建立一個libs資料夾
var qqmapsdk;
qqmapsdk = new QQMapWX({
  key:'DHNBZ-2ZLKK-T7IJJ-AXSQW-WX5L6-A6xxxx'//申請自己的開發者金鑰
});
qqmapsdk.reverseGeocoder({ //逆地址解析api,可以根據你的經緯度去解析位置地址
  location: {
    latitude: latitude,
    longitude: longitude,
},
  success: function (res) {
   conslog.log(res)
    }
        
複製程式碼

第一個坑:如何去獲取經緯度呢,移動markes?,天吶這要寫多少,對於大牛們來說可能分分分鐘,對於剛入門的小生來說難度還是挺大大。沉思良久,突然發現 this.mapCtx.getCenterLocation,移動地圖事件獲取地圖中心的經緯度。那麼我們可以去固定一個 controls在地圖中心,去移動地圖來解析他的座標位置,將資料繫結在下面顯示出來,於是就實現了。emmm程式碼如下

 bindregionchange: function(e){  //移動地圖事件
    var that = this
    this.mapCtx.getCenterLocation({ //getCenterLocation可以獲取地圖中點的經緯度
      success: function (res) {
        app.globalData.strLatitude=res.latitude  //存放到全域性去,供後面計算價格使用
        app.globalData.strLongitude= res.longitude
      qqmapsdk.reverseGeocoder({
        location: {
          latitude:  res.latitude, //通過移動地圖可以得到相應中心點的經緯度
          longitude: res.longitude,
      },
      success: function (res) {
        that.setData({
          address: res.result.address, //得到的經緯度逆地址解析得到我們的位置資訊
          bluraddress: res.result.formatted_addresses.recommend
        })
      },
      });
複製程式碼

第二個坑: 目的地呼叫api一樣可以實現搜尋提示功能,但我需要歷史記錄也存在,並且點選某一項我需要跳轉到首頁顯示出來,沒有歷史的頁面體驗感極差。是否?這裡我是這樣實現的

qqmapsdk.getSuggestion({ //呼叫api實現關鍵詞搜尋提示
      keyword: value, //傳遞input的值,這裡要傳value不是'value',剛開始犯困。提示一下
      region: '南昌', 
      success: function(res){
        let data = res.data
      that.setData({
        address: data, 
        value
      })
複製程式碼
 <view wx:if="{{!value==''}}" class="destination" wx:for="{{address}}" data-destination="{{item.title}}" data-end="{{item.address}}" bindtap="toIndex" wx:key="{{item.id}}">
 
<view wx:if="{{value==''}}" class="destination" wx:for="{{ entity}}" data-destination="{{item.title}}" data-end="{{item.address}}" bindtap="toIndex" wx:key="{{item.id}}">
複製程式碼

通過wx:if去判斷輸入框。下面for不同的陣列,填了第一小坑坑。接下來就會去思考,當我們點選搜尋的怎麼把它加入到我們的歷史中呢?點選獲取那個值的id然後push到歷史陣列中去,是不是很nice,實現了滴滴起始位置的選擇,當然我們這這是冰山一角,強大的背後還需要去探索。

功能三: 費用計算

古人云:細節決定成敗,一個良好的微信小程式往往就是一些細節打動人心,居然是模仿,雖做不到百分百,至少還是很希望一模一樣。

cost
分析分析,首頁點選呼叫快車頁面不跳轉,但要顯示不同的內容。是不是也可以跟上面一樣用wx:if來處理呢?沒錯用一個repeat去承載要顯示的內容,這樣就可以不在刷星這個小技巧get到了嗎。

<repeat wx:if="{{callCart}}">
<repeat wx:else>
複製程式碼

計算價錢一樣用到了騰訊地圖api獲取兩點之間的距離,剛才把起始點都存放在globalData裡,這樣的好處是,可以隨時得到裡面的資料

 let {endLatitude,endLongitude} = app.globalData  //使用ES6的語法去結構資料   
 
 qqmapsdk.calculateDistance({
            mode: 'driving',
            to:[ {
              latitude: endLatitude,
              longitude:endLongitude
          }],
          success: (res)=> {
            var num1 = 8+1.9*(res.result.elements[0].distance/1000)
            var play1 = num1.toFixed(1) //取一位小數點
            app.globalData.play= play1 //同樣存放在全域性裡,後面訂單結束支付要用上
            this.setData({
                play1:play1,
            })
          },
複製程式碼

對於點選顯示的轉態這裡就不詳細描述,本文只針對一些不容易處理的問題。後面司機服務頁面路線規劃也是通過呼叫api,計算兩點的經緯度去標點,連線。這裡也就省略下,詳細的可以參考我的程式碼

功能四: 等待進度

wait
怎樣去做這個頁面呢,或於你以後也需要計時器(不是倒數計時)或者進度條,可以參考這裡。 圓形進度條有很多實現的方法,但我覺得canvas還是挺方便的。兩個canvas搞定

 <canvas class="progress_bg"   canvas-id="canvasProgressbg">  </canvas> //畫底色
 <canvas class="progress_canvas"  canvas-id="canvasProgress">  </canvas> //畫進度條,傳遞一個step引數,用定時器去繪製
複製程式碼

第三坑:繪製canvas沒有問題,文件也給的十分的詳細,但是裡面那個計時器怎麼製作呢?我只需要分秒,而卻又不是倒數計時,並且還要跟外面保持一致。前端這麼心酸的嗎?啊,硬著頭皮去寫吧。搜尋了下資源發現網上這方面的資料真的少。沒有辦法,bug還是要解決的。你是否也遇到過這樣的問題,或於以後呢!記得回來找我...

parseTime: function(time){  // 這裡參考了每個小程式專案中自帶的utils下的util.js,大牛寫的就是簡潔明瞭
  var time = time.toString();
    return time[1]?time:'0'+time;  //自動歸零補零
},
countInterval: function () {
 var curr = 0;
 this.setData({
     time: this.parseTime(timer.getMinutes())+":"+this.parseTime(timer.getSeconds()), //格式化下時間,取分秒
          });
      timer.setMinutes(curr/60); //秒針60了自動加1
        timer.setSeconds(curr%60); //60後歸零
        curr++;
}
複製程式碼

對於同步,那肯定很簡單呀,放在一個定時器裡就夠了。點這裡檢視原始碼

功能五: 取消行程

有叫車就應該有取消對吧,一看取消行程頁面就有點端倪。這些樣式需要自己去寫嗎?要學會說no,這裡就以這個為例子,講下我在小程式開始中如何使用weui快速去搭建一個頁面效果。

clone

這裡給一些我覺得還行的資料:在小程式中可以直接使用的例子 weui小程式官方文件, 要註明的一點,引用weui要在相應的資料夾裡或全域性的wxss引用它的css,可能多個頁面都需要用到,這裡在全域性引用

@import 'styles/weui.wxss';

在app.wxss中引用這段程式碼就可以開始你的weui之旅了,比較囉嗦的貼了這麼長的一段程式碼。暗示你要用weui去快速開發你的小程式了!

 <view class="weui-cells weui-cells_after-title">  //使用weui可以直接複製套上去用就好了
           <checkbox-group   bindchange="bindReasonChange">
               <label class="weui-cell weui-check__label"  wx:for="{{reasons}}" wx:key="value">
                   <checkbox class="weui-check"  value="{{item.value}}"checked="{{item.checked}}"/>
                   <view class="weui-cell__bd name" >{{item.name}}</view>
                   <view wx:if="{{item.checked}}" class="checked "> //點選是顯示紅色的√
                       <image src="../../assets/images/checked.png"></image> 
                   </view>
                   <view wx:if="{{!item.checked}}" class="checked "> //不點選是顯示空圓
                       <image src="../../assets/images/nochecked.png"></image>
                   </view>
               </label>
           </checkbox-group>
           <view class="weui-cell weui-cell_link {{show==true?hidden:''}}">
               <view class="weui-cell__bd moreReasons"  style="display: {{show==true?'none':''}};"bindtap='moreReasons'>
                   <text>點選檢視更多原因</text>
               </view>
               
           </view>
       </view>
複製程式碼

採坑經歷:點選轉態如何解決呢?一開始我是這樣想的,用一個icon通過改變它的checked事件去呈現不同的轉態。這樣是可以實現的,但是隻能點選一個,不能多選。痛苦啊!! 一上午輾轉反側,較勁腦汁。反覆的去看文件,終於豁然開朗起來,可以用多重迴圈去判斷checked。哎,js還是超級重要啊。話不多說

bindReasonChange(e){
 let reasons = this.data.reasons;
 let strVal = e.detail.value;
 for(var i = 0, lenI = reasons.length; i < lenI; ++i){
   reasons[i].checked = false;
   for(var j = 0, lenJ = strVal.length; j < lenJ; ++j){
     if(reasons[i].value==strVal[j]){
       reasons[i].checked =true;
       break;
     }
   }
 }
複製程式碼

以後我們的頁面或多或少可能需要點選選擇功能,其實原理都差不多,這點你得到了嗎,以後再做這方面的功能時就能用上了。總感覺還有什麼沒寫完一樣:好吧!!

在做點選載入更多的,我是這樣打理的。wx:for一個陣列然後去擷取他的下邊顯示。點選載入更多時全部for這個陣列。然後在用定時器設定wx.showLoading()顯示載入更多效果,就有了那種既視感

功能五: 滴滴司機評分

享受了一下滴滴帶來的快捷與方便,感嘆技術的改變生活啊。同樣評分也是app得到使用者最終反饋的直接來源,因此我們也不容錯過這麼重要的一點,但是打理的細節也是十分的坑啊。

end
如何去寫一個評分呢,點選小星星去改變它的轉態,還要根據第幾顆星來判斷前面的也要點亮。真的挺頭痛的,網上不乏小程式評分功能實現,但大多數都寫的不是複雜就是很深奧,對於一個小生來講,簡直就是天書呀。就跟老大說的一樣,很多東西都是靠細節去成長的,想想覺得很容易實現,不就一個status改變一下圖片嗎?但是打理起來真的見功夫。費盡心思去尋找一種簡單粗暴的又可以達到這種效果的方式。

 <view class="evaluation-stars" bindtap="myStarChoose">
    <block wx:for="{{starMap}}"wx:key="{{index}}">
        <text wx:if="{{star>=index+1}}"  class="stars-solid" data-star="{{index+1}}">★</text>
        <text wx:if="{{star<index+1}}"  class="stars-empty" data-star="{{index+1}}">☆</text>
    </block>
</view>
<text class="zan-c-gray-dark">{{starMap[star-1]}}</text>
複製程式碼

不用圖片,用字型去解決這個問題就方便多了,只要改變顏色就達到了評分效果。而且程式碼量非常的少,不知道這樣會不會被打死。

 myStarChoose(e) {
      let star = parseInt(e.target.dataset.star) || 0;
      this.setData({
          star //名字一樣可以省略
      });
  },
複製程式碼

最後一點

把這個放在最後來講,肯定是特別重要的知識點,對於開發的你來說這個比上面功能的描述更有幫助,或於你已經知道並且處理的更好,這裡只為了幫助那些跟我一樣入門不久的小生儘量少走點歪路吧。

  • 1、 資料請求的封裝是搭建一個良好程式的前提。在小程式中我們無時無刻不需要去請求資料。到處充斥做非同步請求,讓我們處理起來很頭疼。這一點更需要發時間去打理的,隨著es6慢慢的普及我們也應該把這些好的東西用到我們的程式碼中promise,把非同步程式設計同步。推薦廖雪峰老師的文章,把我的封裝的貼出來,大家以後可以直接拷過去使用了
let util = {
   request(opt){
       // 生成物件 結構
       let options = Object.assign({},,opt); //es6的賦值
       let {url,data,} = options //es6的結構從options結構出我們需要的url,data
       return new Promise((resolve,reject)=>{
           wx.request({
               url,
               data,
               success(res){
                   resolve(res.data)
               },
               fail(err){
                   reject(err)
               }
           })
       })
   }
}
export default util  //向外輸出模板,在外面可以直接使用util.request({})去網上請求我們的資料的資料了。
              
複製程式碼
  • 2、還有一些就是包的管理,比如把我們頁面中可能一樣的東西抽出來建立一個template資料夾,把一些一樣的wxss也可以抽出來新建一個styles,在需要使用到的地方就@import就可以了,比如滴滴的按鈕吧,其實都一樣,還有頁面底部的橫條都可以封裝起來,用的時候直接匯入就行了。

fitting
功能可能沒有一一列舉出來,由於時間有限,只講述了一些我們日常能使用到的功能。想了解更多功能可以點選這裡檢視我github,本小程式我也會不斷更新,喜歡的話可以加入我。同樣也希望你能夠留下您寶貴的意見和建議。

寄語

作為一個程式猿挺不容易的,做一個前端程式猿更加不容易。技術日新月異。每天要去攝取更多的技術來源,心有千言,難於罄書。但我們都是熱於分享的人,能夠把自己遇到的問題以及如何解決的方式寫出來,總是希望這樣可以幫助到更多同樣遇到這類問題的你,我,他。或於這就是社群的力量,這就是優秀程式設計師的品質吧。小程式的學習依舊要鉚足勁的去學習,後面還有wepy,Mpvue等新技術在等著我們,我已經踏上了那片領地的征程,日後也會發布遇到的問題、bug和我的作品。希望對你有所幫助,我們的口號是熱於分享,熱於創作。Let's start a new journey!!!

相關文章