1. 程式人生 > >小程式雲開發之踩到狗尾巴

小程式雲開發之踩到狗尾巴

前言

前段時間用了下快狗打車,感覺賊方便,師傅響應速度和服務態度都特別好,搬個家再也沒有以前那麼痛苦了,女票也是給了大大的贊。正好最近畢業設計選題跟這個類似,參考了雲開發文件,真心感覺雲函式,雲資料庫,快且好用,立馬開寫,快快搞定畢設,好好工作(歡迎hr小姐姐樓層回覆撩我)。不料,快速雲開發之快狗畢設專案,猶如踩上了狗尾巴,坑坑真多,給各位像我一樣,要快速寫畢設,快速聽女票話搬家的同學,記錄一下。

先給你們看下執行效果:

一、程式骨架的基本構建

1.功能的完整實現

做個東西首先就是要把它的基本功能實現了,這個是毋庸置疑的。如果你是自己準備做個自己的小 程式,那麼你肯定要對自己的小程式應該實現怎樣的功能瞭如指掌,在心裡應該把實現功能的流程 預演個幾百遍了。

這裡第一個坑就出現了,我做的那會可沒有想這麼多,畢竟作為一個愣頭青,莽 就完事了,從想法出來到開始動手時間不到1個小時,事實證明這是非常非常不可取的,也充分暴露 了我經驗的不足。如果你不想像我一樣寫到後面一步一坑的話,最好提前想好。

2.頁面的基本構建

作為一個較大的專案,主頁結構應該做到結構清晰,語義化良好,儘量使用BEM命名規範,當然你要 是想你的程式碼寫完後自己都看不懂,你就瞎**命名當我沒說。

整個頁面大概採用什麼佈局也要事先 想想清楚,當然手機端一般都是彈性佈局比較好,讓你的頁面元素可大可小,完美適配不同尺寸的 手機。

佈局的時候千萬不要捨不得用盒子,如果把佈局比作是整理衣櫃的話,當你的衣服足夠 多的話,一兩個衣櫃顯然是無法滿足條件的,你的衣服將被堆在一起,凌亂不堪。但是如果你有足 夠的衣櫃來放置衣服的話,你的衣服將被分門別類放置的整整齊齊。

在本小程式中,主頁的彈性布 局是將地圖部分設定為flex:1,讓地圖高度隨手機大小來變化,而其他部分保持不變來實現的。 但是在實際執行中,卻總是出現各種問題,最終我的解決辦法是再在頁面中總出問題的部分加入了 一個盒子,又在彈性佈局裡嵌套了一個彈性佈局,這樣首頁的適應性佈局就完美實現了。

3.資料庫的設計

雲開發的釋出,讓後端對於資料的操作變的更簡單了。微信小程式本質上是資料驅動頁面,所以你 想在頁面上展示什麼,就設定一個對應的資料去關聯。然後當我們想改變頁面的時候,只需要改動 資料就可以了。由於我這個小程式資料比較簡單,並沒有把所有的資料都放在雲端,我只建立一張 訂單表orders。

因為訂單裡展示的資訊不多所以只有‘時間’‘發貨地’‘收貨地’‘價格’幾個屬性,‘isdone’是用來標 記訂單是否完成的,表現在頁面中就是訂單狀態會顯示‘已完成’或者‘已取消’

4. 選個好元件庫

這個不是必須的,但是有時候選擇到一個適合的元件庫用起來真的爽,可以讓你的開發事半功倍 我選的是vant(這個我選的就不是很好),希望你能選上一個讓你用完發出一句真香感慨的。

二、程式功能的基本實現

如果你已經完成了上面的前三步,那你簡直比我好太多了!剩下的只不過是將功能一個一個新增上 去罷了。由於本程式的實現使用了大量api,我不會去把這些api一個個詳細講解,這樣純粹是浪費 時間。但是我會把一些實現想法和一些我遇到的坑像大家說明,避免你們像我一樣踩坑。

1. 實時獲取點的座標並將地址顯示在頁面

仔細看了演示圖的同學會發現當我移動地圖時,起點的地址是在實時發生變化的,當我停止拖動 地圖時,起點的地址就會更新到最新點。那麼這個功能是如何實現的呢?其實這裡是有一點巧妙的。

實際上我用cover-image在地圖上標記了一個起點,這個點是一直垂直居中固定在地圖的中心的 。這樣我只需要獲取這個中心點的座標並使用逆地址解析就能得到這個點的位置描述啦,是不是有 點巧妙。而怎麼獲取中心點的座標和完成逆地址解析呢,當然這一切都有騰訊爸爸提供給我們的ap i去完成了。這裡有個注意的點就是我們應在使用者鬆開時來顯示更新後的地址,bindregionchang這 個可以做到,當e.type = end時再顯示就可以了,細節雖然小,但是還是不能忽視了。

2. 輸入地址時要能有模糊搜尋提示

這個效果主要依賴於騰訊地圖小程式jsSDK中的輸入關鍵詞提示,呼叫這個介面我們將可以在返回 值中拿到一個數組,裡面包含著我們需要的各種資訊。拿到資料是很簡單的,但是如何處理它呢? 這個陣列的長度是不固定的,其實很簡單我們只需要將拿到的資料setData給一個我們定義的空數 組searchresult,這樣所有的資料就到了這個數組裡,到時候再去頁面上迴圈這個陣列,這樣我們 就可以將裡面的資料都拿出來並讓它們顯示在它們該顯示的地方,所以這部分的關鍵在wxml裡,下 面是我寫的:

<view class="content">
  <scroll-view class="scrollcontent" scroll-y style="height: {{scrollheight}}rpx;">
    <block wx:for="{{searchresult}}" wx:key="index">
      <van-cell-group border="{{true}}">
        <van-cell class="resultlist" title="{{item.title}}" border="{{true}}" data-title="{{item.title}}"
        data-location="{{item.location}}" icon="location" label="{{item.address}}" bind:click="getlistvalue"/>
      </van-cell-group>
    </block>
  </scroll-view>
</view>
複製程式碼

3.主頁車型切換並帶來價格的變化

這個需求是讓顧客可以自由選擇車型,這個有點類似滴滴打車的‘快車’'拼車'‘優享’。剛開始做的 時候我以為這是一個scroll-view和scroll-into-view配合來實現的。等到我把一切基本都實現了的 時候,最後一個效果就是實現滑動切換時劃過一定距離就自動進入下一頁,不夠據距離就回彈。我 想了很多方法來判斷,各種js判斷各種利用scroll-left都搞不定。

直到我無意中在官方文件中看到 了swiper這個元件,這絲般順滑的滑動切換,距離夠了自動下一頁,不夠就回彈,這不就正是我所 需要的嗎,於是我直接刪了原來的程式碼,花了不到半個小時就擼完了這個小元件(核心在於判斷cur renttab與index是否相等,注意這個index後面還有大用)。

看到這完美效果的我不禁淚流滿面。所 以這件事告訴我們當你一直搞不定某個效果時,你應該靜下心來想想是不是你開始就弄錯了方向, 避免做無用功,浪費時間。接下來奉上我完美實現的程式碼(wxml和js部分):

wxml:

<view class="container">
    <view class="container-header">
    <view class="carLists {{currentTab === index ?'on': ''}}" wx:for="{{carName}}" wx:key="index" data-id="{{item.id}}" data-index="{{index}}" bindtap="switchTab">
      {{item.name}}
    </view>
    </view>
    <block wx:if="{{index>0}}">
        <van-icon name="arrow-left" class="arrow-left" bind:click="last" />
    </block>
    <block wx:if="{{index<3}}">
        <van-icon name="arrow" class="arrow" bind:click="next" />
    </block>
    <swiper class="carList" current="{{currentTab}}" bindchange="swiperChange">
      <block wx:for="{{cars}}" wx:key="index">
        <swiper-item class="carview">
          <image class="carImg" src="{{item.image}}" mode="aspectFill"/>
        </swiper-item>
      </block>
    </swiper>
  </view>
複製程式碼

js:

switchTab:function(e){
      if (this.data.currentTab === e.target.dataset.index) {
        return;
    } else {
        this.setData({
            currentTab: e.currentTarget.dataset.index,
            index:e.currentTarget.dataset.index
        })
    }
  },
  
  
  swiperChange:function(e){
    // console.log( e.detail)
    if(e.detail.source == 'touch'){
      this.setData({
        currentTab: e.detail.current,
        index:e.detail.current
    })
    }
   
  },
    next:function(e){
      // console.log(this.data.currentTab,this.data.currentTab)
       if (this.data.currentTab === this.data.index && this.data.currentTab <3 ) {
          this.setData({
            currentTab:this.data.currentTab + 1,
            index:this.data.index +1
          })
        }
       
    },
  
    last:function(e){
      if (this.data.currentTab === this.data.index && this.data.currentTab > 0 ) {
        this.setData({
          currentTab:this.data.currentTab - 1,
          index:this.data.index -1
        })
      }
    }
複製程式碼

4.關於距離及價格的計算

之前在輸入起點和終點的時候我們可以通過騰訊地圖的api拿到兩者的具體座標,這裡我採用的距 距離計算沒有采用騰訊地圖所提供的api(因為有距離限制,僅限10km以內),這個距離對於我們來說 無疑是太短了,於是我採取了一個通用公式,只要能有兩地座標,便可以算出兩地間的距離,這樣 一來我們的老司機們就不用再受到距離的限制了。

//計算兩座標點之間的距離
      distance: function (lat1, lng1, lat2, lng2) {
        const rad1 = lat1 * Math.PI / 180.0;   
        const rad2 = lat2 * Math.PI / 180.0;   
        const a = rad1 - rad2;   
        const b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0;  
        const r = 6378137;
        const distance = (r * 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(rad1) * Math.cos(rad2) * Math.pow(Math.sin(b / 2), 2)))).toFixed(0)
        return distance / 1000;//單位轉化為公里
      }
複製程式碼

現在我們拿到了距離,但是怎麼能讓價格根據所選車型來動態變化呢?還記得之前頁面裡給每個 滑塊的index嗎?這裡我們恰好就可以用它來做一個switch判斷,給getPrice函式傳入一個index 引數判斷不同值並給出不同的計價方式,這樣一來價格變會隨著車型的切換而變化了。最後我們 的效果就達到了。

5.訂單完成資料的上傳及拉取

有了雲開發之後資料庫的操作簡直不要太簡單了!取消訂單時,在選擇完取消訂單理由後,們 將向雲資料庫新增一條資料,只需幾條命令我們就可以將我們的資料真正的存在資料庫裡並儲存起 來,聽上去是不是很心動呢

wx.cloud.init();//初始化
const db = wx.cloud.database();
const cancelOrder = db.collection('orders')//orders為手動在雲資料庫裡新增的一張空表
//三步操作後我們就連上了我們的資料庫
    cancelOrder.add({
      data:{
        time:globalData.time,
        shipAddr:globalData.address,
        receiveAdrr:globalData.receiveAdrr,
        price:globalData.price,
        isdone:false
      }
    })
複製程式碼

這樣訂單資料就被我們新增到了資料庫裡,可以被我們隨時訪問了。然後在通過一條簡單的查 詢語句就可以在我的訂單裡顯示了。

    orders.where({
      _openid:'xxxxxxxx'//使用者的openid
    }).get({
      success: res=> {
        this.setData({
          orders:res.data
        })
        // console.log(res.data)
        wx.hideLoading();//載入完成關閉載入框
      }
    })
複製程式碼

最後在頁面上迴圈輸出orders裡的值就可以得到一堆訂單了

寫在最後

一個完整專案的實現確實不是那麼簡單的,即使是一個簡單流程的實現,很多看似簡單的東西 裡經常藏著大坑,而不同頁面之間的聯絡也是很讓人頭痛的,我們要從之前那種區域性的眼光中跳脫 出來,從更大的層面來看待構建我們的專案骨架。

使用元件化,函式化的程式設計思想可以很好的幫助 我們降低程式碼的耦合性,增加程式碼的複用性,使我們的程式碼結構更清晰。寫本篇文章的目的是為了 方便自己以後重構專案的時候看,也是為了給有跟我一樣想法,躍躍欲試想擼個完整專案的同學一 個參考,少踩一些坑。

最後有什麼建議或者文中有什麼錯誤的地方歡迎在評論中指出,互相學習, 共同進步!

這是我在掘金髮的第一篇文章,看完覺得還不錯的同學點個贊再走吧!

完整專案點這:專案地址

主要參考:

  1. 快狗打車拉貨搬家微信小程式
  2. 微信小程式官方文件:developers.weixin.qq.com/miniprogram…
  3. 騰訊地圖api文件:lbs.qq.com/qqmap_wx_js…
  4. vant Weapp小程式ui元件庫:youzan.github.io/vant-weapp/…