A計劃小程序的血與淚

前言

A計劃只是一個代號,不表明任何小程序css

微信小程序,簡稱小程序,英文名Mini Program,是一種不須要下載安裝便可使用的應用,它實現了應用「觸手可及」的夢想,用戶掃一掃或搜一下便可打開應用。前端

最近兩週因爲公司業務需求,本胖主導開發了一款功能簡單的小程序—A計劃(如下本次開發小程序的代號),能夠說這兩週本胖都是在瀏覽小程序官網以及小程序論壇,適應小程序的開發模式以及填開發過程當中的大坑小。這裏須要說一句,本身平時作demo和開發公司級別的正式項目永遠都是兩碼事哈,本胖此次也是深有體會,不少以前作demo時候只是模棱兩可的知識在此次開發中獲得了深刻認識,還有就是對小程序開放能力的深刻理解,知道了小程序能作什麼,小程序不能作什麼,因此敬以此文記錄本胖對小程序的認知,若有錯誤,煩請指出,謝謝。vue

1 小程序登陸以及受權

1.1 小程序登陸

任何項目都會涉及到登陸這個問題,在JSP的遠古時代登陸都是直接由服務端控制,在如今react,vue單頁面時代,登陸是有客戶端控制,因此如今的不少前端框架都會有全路由守護這種東西,能很方便地幫助咱們控制路由權限,那麼在小程序裏面的登陸時怎麼控制的呢?react

小程序裏面的登陸主要分2種ios

A. 利用現有登陸體系web

直接複用現有系統的登陸體系,只須要在小程序端設計用戶名,密碼/驗證碼輸入頁面,即可以簡便的實現登陸,只須要保持良好的用戶體驗便可。
複製代碼

B.利用OpenIdajax

OpenId 是一個小程序對於一個用戶的標識,利用這一點咱們能夠輕鬆的實現一套基於小程序的用戶體系,值得一提的是這種用戶體系對用戶的打擾最低,能夠實現靜默登陸。具體步驟以下:

1.小程序客戶端經過 wx.login 獲取 code

2.傳遞 code 向服務端,服務端拿到 code 調用微信登陸憑證校驗接口,微信服務器返回 openid 和會話密鑰 session_key ,此時開發者服務端即可以利用 openid 生成用戶入庫,再向小程序客戶端返回自定義登陸態

複製代碼

此次因爲須要獲取用戶手機號的,因此咱們選擇了第二種(注意了,我的主體的小程序號是獲取不了用戶手機號的)。可是這裏須要強調的一點是登陸和受權獲取用戶信息(好比手機號,頭像,微信步數)是兩回事情,不要搞混淆了,登陸是能夠作到靜默登陸的,可是不多有小程序只作一個登陸的,那會是一個沒有靈魂的小程序哈。json

1.2 受權

這裏不得不認可,微信是中國流量最大的app,全部小程序纔有了生根萌芽的沃土,作小程序就不得不涉及到相關用戶權限的受權。A計劃小程序此次涉及到受權的地方主要是獲取用戶手機號,還記得那年夏天微信小程序獲取手機號仍是能夠直接經過API方式直接彈出受權彈框的,此次發現居然不行了,只好去官網看看改動了哪些(不得不說這也是小程序的不肯定性,一家獨大,想改就改),發現如今要獲取用戶手機號只能經過引導用戶觸發相應的按鈕才行。canvas

1.3 登陸+受權解決方案

此次本胖採用的方案是專門用一個頁面(login)來進行用戶的登陸以及受權,這裏須要注意的是,你在取微信用戶綁定的手機號,需先調用wx.login接口。小程序

咱們首先須要下面這個button組件用來引導用戶觸發登陸

<button type="primary" open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">微信登陸</button>
複製代碼

而後須要在login頁面的onload事件中發起wx.login(),獲取對應的code存起來。 關鍵的一步到了,在用戶點擊肯定受權的按鈕,咱們須要監聽getPhoneNumber事件

getPhoneNumber(e) {
    if (e.detail.iv) {
      this.setData({
        iv: e.detail.iv,
        encryptedData: e.detail.encryptedData
      });
      this.login(this.getPhone);
    }
}
複製代碼

注意到上面最後一行的代碼,是在獲取到iv以及encryptedData這兩個解密用戶手機號必備的變量的時候纔去發起登陸以及獲取對應的手機號前端顯示用。

能夠看到上面的微信登陸按鈕其實一開始是先作了一個獲取用戶手機號權限的操做,操做成功後才登陸的,若是一開始就登陸了,可是用戶沒有贊成受權手機號,那麼將變得毫無心義,由於手機號纔是小程序須要快捷獲取的核心用戶信息之一。

登陸完成後客戶端能夠獲取到一個自定義token。相似於瀏覽器裏面的JSSSESIONID,能夠存小程序本地,在須要的時候手動帶上就能夠了,這一點比不了瀏覽器能夠設置自動帶上cookie那麼方便。

2 生成海報

爲何不少小程序裏面都會有生成海報呢,其實也是由於小程序不能直接轉發到朋友圈,不能直接轉發到QQ以及其餘社交平臺,那麼就須要出現海報這個中間傳播者。此次A計劃小程序裏面也有這個功能,因而本胖就愉快地開始了海報的填坑。

小程序的海報通常都是經過canvas生成的,也就是填小程序canvas的各類坑哈。

2.1 實體機海報空白

上圖中就是在生成海報的時候出現的實體機空白問題,可是在模擬器裏面卻不會有,在查閱了不少資料之後發現是圖片資源沒能及時加載出來,就會形成在drawImg的時候沒有真實的圖片能夠畫,固然就是空白了。

既然是由於在畫圖的時候圖片沒有及時請求到形成的問題,那麼解決的方案固然就是在頁面初始化的時候就去異步請求圖片

downloadFile(url, name) {
  wx.downloadFile({
    url: url,
    success: function (res) {
   
    }
  });
}
複製代碼

2.2 背景圖片自適應

canvas是須要設置大小的,不然取他的默認大小。可是canvas的單位是px和小程序標準的單位rpx是不一樣的。因此咱們須要動態給canvas區域設置寬高才能讓canvas滿滿填充整個理想區域。

createNewImg: function (text) {
  wx.createSelectorQuery().select('#canvas-container').boundingClientRect( (rect) => {
      this.setData({
        canvasW: rect.width,
        canvasH: rect.height
      });
      var width = this.data.canvasW,
        height = this.data.canvasH,     
        context = wx.createCanvasContext('mycanvas');
      context.drawImage(this.data.imgUrl1, 0, 0, width, height);
      context.draw();
    }).exec();
  },
複製代碼

上面的代碼就是用過獲取不一樣屏幕下canvas的包裹元素的寬高而後動態給canvas賦值,而後對應圖片的畫圖也是一個道理,就可讓圖片只適應不一樣屏幕。

2.3 文字居中

好了,畫好了主圖本胖就要在主圖寫字了,需求是寫一段文字,字數不定,居中顯示。

本胖一開始想固然了用了setTextAlign設置了文字的對齊方式,但是一看居然沒有說明用,因而本胖只好想算出全部文字的所有長度,用區域寬度減去文字的長度除以2設置文字的起始X座標就能夠了。

context.fillText(`我是呂胖胖`, (width - context.measureText(`我是呂胖胖`).width) / 2, );
複製代碼

上面代碼裏面的measureText就是解決問題的核心API。

2.4 canvas層級過高 致使ios中海報隨着屏幕滑動

由於海報主體使用了fixed佈局,因此會被固定在屏幕的中間,在模擬器裏面測試沒有問題,可是在ios上面會出現手指滑動海報,海報會隨着頁面滑動,這是否是看起來很滑稽。這種現象是由於canvas這東西在小程序裏面地位那是至關的高,下面是小程序對canvas的介紹。

canvas組件是原生組件,他有以下的限制

原生組件的使用限制
因爲原生組件脫離在 WebView 渲染流程外,所以在使用時有如下限制:

原生組件的層級是最高的,因此頁面中的其餘組件不管設置 z-index 爲多少,都沒法蓋在原生組件上。
後插入的原生組件能夠覆蓋以前的原生組件。
原生組件還沒法在 scroll-view、swiper、picker-view、movable-view 中使用。
部分CSS樣式沒法應用於原生組件,例如:
沒法對原生組件設置 CSS 動畫
沒法定義原生組件爲 position: fixed
不能在父級節點使用 overflow: hidden 來裁剪原生組件的顯示區域
原生組件的事件監聽不能使用 bind:eventname 的寫法,只支持 bindeventname。原生組件也不支持 catch 和 capture 的事件綁定方式。
在iOS下,原生組件暫時不支持觸摸相關事件。
原生組件會遮擋 vConsole 彈出的調試面板。
在工具上,原生組件是用web組件模擬的,所以不少狀況並不能很好的還原真機的表現,建議開發者在使用到原生組件時儘可能在真機上進行調試。
複製代碼

一開始本胖查閱資源後大部分是設置以下

disable-scroll='true'
複製代碼

可是試事後並無什麼軟用,最後無心間忽然發現了一個好用的屬性

catchtouchmove='true'
複製代碼

該屬性加在海報最外面的view上面。

3 生成小程序碼+自定義分析

其實微信小程序自己就自帶了數據分析,裏面有不少好比統計小程序的訪問量,訪問分析,用戶畫像等等。固然了,若是你和本胖同樣對這些統計不知足的話,你還能夠本身定義一些統計。本胖此次的需求是以下

生成N個小程序碼,而後區別不一樣渠道的流量

3.1 生成多個小程序二維碼

目前小程序二維碼有二種,一種是普通的正方形的(體驗版本就是這種),還有一種是小程序官方爲了區別其餘二維碼而專門設置的圓形的體驗碼,下面所說的體驗碼都是圓形的體驗碼,目前只能經過請求小程序官方接口獲取。本胖採用的請求A類接口才獲取二維碼

https://api.weixin.qq.com/wxa/getwxacode?access_token=ACCESS_TOKEN
複製代碼

這個接口須要獲取一個叫作access_token的東西

下面是獲取access_token的接口

GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
複製代碼

好了,接下來就是愉快地獲取二維碼了。這時候又一次見識到小程序坑爹的地方了。

本胖愉快地寫了一個本地ajax請求(必定要post),代碼以下:

$.ajax({
  method: 'post',
  url: 'https://api.weixin.qq.com/wxa/getwxacode',
  dataType: 'json',
  data: {
    access_token: 本胖的accesss_token
    path: 'pages/index/index?id=1',
  },
  success: (data) => { 
    console.log(data);
  }
});
複製代碼

發現報錯,參數爲空,再去看官方發現有下面的提示

哦哦,原來是要json字符串,而jq默認是contentType是application/x-www-form-urlencoded,因而本胖很快按照提示改爲了下面的contentType

contentType: "application/json; charset=utf-8"
複製代碼

這會總該能夠了吧。

沒想到又是接受不到參數。。。。

最後在嘗試了不少次之後終於發現了正確的請求方式

$.ajax({
  method: 'post',
  url: '/wxa/getwxacode?access_token=本胖的accesss_token',
  dataType: 'json',
  contentType: 'text/plain;charset=UTF-8',
  data: JSON.stringify({
    path: 'pages/index/index?id=1',
  }),
  success: (data) => { 
    console.log(data);
  }
});
複製代碼

有沒有很驚喜,有沒有很意外。這種設計真的很蛋疼,小程序官方最好給一個請求實例哈。

3.2 自定義分析 好了,經歷了千辛萬苦的嘗試,本胖在上一屆總算請求到了A計劃的小程序圓形碼了。接下來就是作自定義分析。

所謂自定義分析,在小程序後臺管理系統是能夠找到的,顧名思義就是咱們能夠本身定義一些用戶行爲的分析,好比用戶點擊某個按鈕的次數,用戶停留在某些頁面的時間等等,能夠說是小程序官方留給開發者埋點的口子

看了一下關於自定義分析的介紹(文章真的很長很長),知道了自定義分析主要步驟以下

1.新建事件
2.選擇配置方式
    A.填寫配置:不須要任何小程序代碼
    B.API上報:須要加對應的小程序代碼
3.保存測試或者發佈
複製代碼

注意到了在選擇配置方式的時候是有2種的,本胖此次需求是要經過不一樣的小程序碼區別不一樣渠道的流量,因此選擇了第二種。

對了,這裏須要說明以前在獲取小程序碼的時候path參數,本胖在路徑後面是傳了參數的,這個參數就是用來區別不一樣渠道。

而後配置好後,能夠獲取到對應的上報代碼

wx.reportAnalytics('statistics', {
  id: '',
});
    
複製代碼

這裏看出本胖是選擇了一個名稱是statistics的事件名稱,而後本胖在A計劃小程序的首頁的onload事件中加入瞭如下代碼

onLoad: function(options) {
  console.log(options);
  wx.reportAnalytics('statistics', {
    id: options.id
  });
}
複製代碼

那麼不一樣渠道的小程序進入就會獲取到不一樣的id上報給小程序平臺,在後臺管理中根據不一樣的渠道id的上報次數來判斷不一樣渠道的流量狀況

可是,現實有這麼美好嗎?

在體驗版的小程序的路徑中加入了不一樣的id,體驗了一把,去小程序的後臺查看對應的數據(本胖的自定義事件已經發布),有下面的截圖

看的只是不一樣id的去重總和數據,並無不一樣id對應的數據,也就說經過小程序的自定義分析實現不一樣小程序碼區別不一樣渠道的想法是不行的,該次嘗試以失敗了結,也讓本胖知道了小程序有哪些是還作不了的,因此說這樣的嘗試也是有意義的哈。

對於這個需求,本胖最終仍是打算採用咱們本身的服務端來實現不一樣渠道的流量分析。

4 其餘坑點

哈哈,這一節的標題不知道取什麼好了,只好取了這個。

4.1 橫向滾動

作H5的時候,實現橫線滾動那是so easy的事情,你們都懂哈,不就是一個熟悉的問題嘛。 可是,這麼簡單的需求在小程序裏面並無那麼簡單。

<view>
  <scroll-view scroll-x>
  </scroll-view>
</view>
複製代碼

像上面這樣,設置了scroll-x屬性就覺得當scroll-view 的內容超出scroll-view 時候會出現橫向滾動條,可是實際上並非這樣的,還須要下面的設置

scroll-view
  white-space: nowrap;
子元素
  display: inline-block;
複製代碼

white-space:nowrap;這個屬性在css裏面的意思是

規定段落中的文本不進行換行

4.2 inupt動態綁定

嘗試太小程序的都發現他的語法和vue很像,因此上手都是很快的。可是當本胖遇到input的時候果斷寫了下面的代碼

<input value="{{name}}">
複製代碼

想經過這種方式的綁定來動態獲取到輸入框輸入的值。

可是現實又是殘酷的。

人家小程序根本就不支持這種寫法。

有沒有很坑,都向vue學習了90%的語法了,input綁定變量使用評率這麼高的居然不學。

吐槽歸吐槽,活仍是要繼續幹下去的。只好採用react版方式來動態獲取input的輸入值了。

this.setData({
  val: e.detail.value
});
複製代碼

4.3 wx.request

這是小程序用來獲取服務端數據的api,使用頻率那也是很高的,可是他在本胖看來主要有2處須要注意的地方

1.默認的contentType是application/json,須要本身改寫爲合適的和服務器端通信
2.和傳統的ajax很像,容易走入回調地獄,能夠本身封裝成promise形式哈
複製代碼

5. 小結

這篇文章主要是總結了本胖這兩週在開發A計劃小程序遇到的問題以及對應的解決方案和對微信小程序的一些我的見解。

不過,微信小程序的確能夠說是前端史上一次重大的突破,其體驗,能力(雖然大部分也都是經過使用微信app的能力)都比通常的H5更好更強。並且語法和vue很像,易於上手,開發體驗也不錯,相應的社區工具都愈來愈完善了,很期待小程序的將來。

這應該是本胖工做2年多來寫的最長的一篇技術博文了,二年多時間說過就過,本胖惟有努力使本身的能力與年齡成正相關才行哈。

相關文章
相關標籤/搜索