最近時常感嘆道:時間老是那麼的快,轉瞬即逝。對於像我這種剛入門的小生來說,技術天天都在更新,框架也層出不窮,有時候還沒弄懂這個知識大牛們又推出了更好的技術。固然學習好的技術也是十分重要的。可是在學習以後怎樣纔可以獲得本身想要的呢,一個好的建議即是靜下心來寫點本身的東西,哪怕你完成不了也應該盡力去寫,老大曾講過要去實踐要去獨立思考,你才能掌握不少你看似懂了卻又很難處理的知識點。學習小程序的我已通過去了半個月了,前不久滴滴事件頗爲轟動,因而便萌發了這篇文章,打開滴滴的小程序。界面作了很大的變化,對於比較懷舊的我來講,仍是挺喜歡之前的界面,因而決定打算本身手寫一個懷舊版滴滴小程序,接下來我會列舉我所遇到的坑和如何解決的方法,但願可以幫到一樣在奮鬥的你...css
工欲善其事必先利其器,對於一個前端來講有一個好的工具可以讓咱們事半功倍。要想作好一個小程序咱們首先也應該先選擇咱們的兵器。html
數據接口前端
說了一大堆,等於沒說,仍是回到正題,先來一波效果圖。
這裏有更多的圖片等你
vue
接下來我會對滴滴微信小程序主要功能,以及對應的數據接口和採用的組件/API技術,描述的詳細。讓咱們離小程序更近一點,傳遞知識,分享收穫git
功能描述:頂部導航的製做,點擊相應的nav頁面呈現不一樣的內容,而且點擊時能判斷是向前仍是向後自動滑出下一個nav,實現動畫過分效果。輸入起始位置模擬等待的時間。
實現原理:程序員
<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>
在須要用到加載效果的地方就能夠直接使用,es6
<import src="/templates/sprinner.wxml" /> <template is="sprinner" data='{{isLoading}}'> </template> //經過去設置isLoading的布爾值來判斷是否須要顯示
<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,而後超出則隱藏。坑啊,根本就實現不了。沒法判斷左滑出仍是又滑出,後來又想到設置一個閾值。累真的難寫。好像放棄啊,仍是堅持下吧,因而想到分開來取寫他們的jsgithub
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對於地圖這方面講的確實不怎麼詳細,多是我這種對地圖處理天生迷茫的人。這裏將詳細的把我遇到的問題一一列舉出來,但願也可以幫助到從此的你去處理地圖這種東西少踩點坑吧。
這裏使用到了關鍵詞搜索,逆地址解析,地址解析,切換城市列表,建議之後作這個能夠了解下騰訊地圖api,仍是比較方便的canvas
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,實現了滴滴起始位置的選擇,固然咱們這這是冰山一角,強大的背後還須要去探索。
古人云:細節決定成敗,一個良好的微信小程序每每就是一些細節打動人心,竟然是模仿,雖作不到百分百,至少仍是很但願如出一轍。
分析分析,首頁點擊呼叫快車頁面不跳轉,但要顯示不一樣的內容。是否是也能夠跟上面同樣用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,計算兩點的經緯度去標點,連線。這裏也就省略下,詳細的能夠參考個人代碼。
怎樣去作這個頁面呢,或於你之後也須要計時器(不是倒計時)或者進度條,能夠參考這裏。
圓形進度條有不少實現的方法,但我以爲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快速去搭建一個頁面效果。
這裏給一些我以爲還行的資料:在小程序中能夠直接使用的例子 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獲得用戶最終反饋的直接來源,所以咱們也不容錯過這麼重要的一點,可是打理的細節也是十分的坑啊。
如何去寫一個評分呢,點擊小星星去改變它的轉態,還要根據第幾顆星來判斷前面的也要點亮。真的挺頭痛的,網上不乏小程序評分功能實現,但大多數都寫的不是複雜就是很深奧,對於一個小生來說,簡直就是天書呀。就跟老大說的同樣,不少東西都是靠細節去成長的,想一想以爲很容易實現,不就一個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 //名字同樣能夠省略 }); },
把這個放在最後來說,確定是特別重要的知識點,對於開發的你來講這個比上面功能的描述更有幫助,或於你已經知道而且處理的更好,這裏只爲了幫助那些跟我同樣入門不久的小生儘可能少走點歪路吧。
一、 數據請求的封裝是搭建一個良好程序的前提。在小程序中咱們無時無刻不須要去請求數據。處處充斥作異步請求,讓咱們處理起來很頭疼。這一點更須要發時間去打理的,隨著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({})去網上請求咱們的數據的數據了。
二、還有一些就是包的管理,好比把咱們頁面中可能同樣的東西抽出來建立一個template文件夾,把一些同樣的wxss也能夠抽出來新建一個styles,在須要使用到的地方就@import就能夠了,好比滴滴的按鈕吧,其實都同樣,還有頁面底部的橫條均可以封裝起來,用的時候直接導入就好了。
功能可能沒有一一列舉出來,因爲時間有限,只講述了一些咱們平常能使用到的功能。想了解更多功能能夠點擊這裏查看我github,本小程序我也會不斷更新,喜歡的話能夠加入我。一樣也但願你可以留下您寶貴的意見和建議。
做爲一個程序猿挺不容易的,作一個前端程序猿更加不容易。技術突飛猛進。天天要去攝取更多的技術來源,心有千言,難於罄書。但咱們都是熱於分享的人,可以把本身遇到的問題以及如何解決的方式寫出來,老是但願這樣能夠幫助到更多一樣遇到這類問題的你,我,他。或於這就是社區的力量,這就是優秀程序員的品質吧。小程序的學習依舊要鉚足勁的去學習,後面還有wepy,Mpvue等新技術在等着咱們,我已經踏上了那片領地的征程,往後也會發布遇到的問題、bug和個人做品。但願對你有所幫助,咱們的口號是熱於分享,熱於創做。Let's start a new journey!!!