1. 程式人生 > >微信小程式的程式設計模式

微信小程式的程式設計模式

作者簡介: 範懷宇,輕芒聯合創始人,畢業於清華大學,前豌豆莢技術負責人,專注於移動開發十餘年,曾出版《Android 開發精要》。愛研習好程式碼和設計,相信好的產品能改變生活,好閱讀樂分享。 
責編:唐小引,技術之路,共同進步。歡迎技術投稿、給文章糾錯,請傳送郵件至[email protected]。 
宣告: 本文為《程式設計師》2017年1月期原創文章,未經允許請勿轉載,更多精彩文章請訂閱 2017 年《程式設計師》

導讀: “輕芒小程式+”是由輕芒團隊提出的小程式解決方案,它將替內容創業者免費搭建屬於自己的微信小程式。在進行“輕芒小程式+”和其他小程式應用開發的過程中,本文作者與其團隊對當前正火熱的小程式開發有了更為深度的理解與認識,進而有了本文。(這裡還有一篇滿載真誠的

微信小程式開發乾貨,點選查閱。)

從小程式誕生伊始,就有很多人開始研習其機理與特點,從原始碼或整體架構的角度已經有很多不錯的文章會令人受益。但理論是一回事,真正理解小程式,還需要實踐,才能進一步理解其背後的想法,與已有平臺的異同,以及如何去適應它,做出更有趣的小程式。

理解開發平臺的特性,一個不錯的角度就是從程式設計模式入手,看在這個平臺上開發,需要如何書寫和組織自己的程式碼,進而搞清楚三個問題:

  1. 資料如何獲取;
  2. 介面如何呈現;
  3. 互動如何傳導。

換而言之,就是從 MVC(Model-View-Controller)的視角去拆解這個平臺的特性,從而理解其開發有何特點。

資料如何獲取

程式的本質,可說就是資料的呈現和加工。所以,看一個客戶端開發平臺的基本能力,首先就要看能把哪些資料放在上面處理,有哪些侷限?如果缺少了必要的資料獲取方式,那對於開發者而言,巧婦也難為無米之炊。

從這點看,小程式提供的資料獲取方式非常豐富,大概涵蓋:

  • 通過 HTTPS 請求去服務端獲取資料。支援 HTTPS 是最基本的,小程式對 HTTPS 有限制,除了要求通訊協議是 HTTPS,出現的域名必須提前預設之外,還將應用層協議限定到了 JSON 格式下。這一點,可能比任何一個已有客戶端平臺都更為嚴苛。站在小程式的平臺角度來看,通過這樣的協議規定,對應用中流動的資料有了更強的管控能力;而對於開發者而言,則需要花些時間去調整自己的服務協議以便適應小程式的要求。
  • 可以在本地檔案系統上存取資料。小程式提供了豐富的 API 供開發者在手機系統上存取檔案。可用本地檔案來做快取、狀態記憶等,為開發提供了便利。
  • 可以讀寫裝置中的一部分資訊。小程式開放了一些 API,幫助開發者獲得裝置上的基本資訊,比如手機型號、螢幕尺寸、網路狀態等。較為有價值的是可以選擇獲取手機上的圖片等多媒體檔案,這給做影象應用提供了可能;並且,它還提供了羅盤、重力感應器、地理位置等資訊,對開發者理解使用者所處的環境大有裨益。

從上面的介紹不難看出,小程式中的資料獲取方式,和一般瀏覽器提供的相仿(也就是和 HTML5 應用能獲取的資訊),比原生的客戶端更侷限一些,但對於絕大多數的應用而言足夠用了。

除此之外,小程式提供了微信生態中的一些資料,比如賬號資訊等。這對於微信龐大的生態而言,只是非常小的一部分資料,但卻是開發小程式應用中最值得利用的資料。

舉個例子,在其他平臺上,如果想要獲取微信的賬號資訊,需要通過一次使用者授權。假如使用者暫時不想提供,則會使程式呈現“未登入”狀態,給整個服務的展開帶來困難。而在小程式中,只要使用者點開,就意味著完成了授權,開發者可以直接讀取到小程式的賬號資訊,並同步到自己的服務端作為該使用者的身份標識,從而實現“始終登入”的狀態,使得後續服務可以更好地提供。

一份可行的示例如下:

// 先呼叫登入介面,獲得請求碼
wx.login({
    success: function (res) {
        // 獲取到請求碼,繼續請求使用者的基本資訊
        var code = res.code
        wx.getUserInfo({
            success: function (res) {
                // 獲取到了加密的使用者資訊,去服務端解密並存儲
                var userData = res.encryptedData
                var iv = res.iv
                wx.request({
                    url: 'https://my_account/...',
                    data: {
                        code: code,
                        user_data: userData,
                        iv: iv
                    },
                    success: function(res) {
                        // 在伺服器上,解析並生成自己的賬號驗證資訊
                        var user = res.data.user
                        var token = res.data.token

                        // 並且還可以存在本地儲存上,供下次開啟使用
                      wx.setStorage({
                            key: 'my_token',
                            data: token
                      })
                    }
                })
            }
        })
    }
});

介面如何呈現

小程式剛釋出的時候,一片人開始驚呼 HTML5 的時代就要到來了,因為小程式在介面層使用了 HTML/CSS/JavaScript 這套 HTML5 的技術棧。但很快,隨著聰明的程式設計師們對小程式的理解進一步加深,就發現小程式所說的 HTML/CSS/JavaScript 和 HTML5 中的完全不是一回事,其差異基本等同於 Java 和 JavaScript。

在小程式中,和 HTML 對應的是 WXML,保留下來的只有 HTML 的概念,而傳統的<div><a>標籤都完全被拋棄了。和 Facebook 的 React 類似,小程式引入了自己的 HTML 標籤,它和 <article〉<section> 這樣的語義標籤不同,小程式中的標籤更像是傳統客戶端開發中的元件(或者叫控制元件),每個元件都有自己背後的職能和使用方式。比如:如果需要展示圖片,就只能用標籤,其他的都無法承載。而如果需要提供可選的文字,則只能使用<text>標籤等。

這樣的方式帶來最大的問題就是傳統的 HTML 頁面都無法在小程式中呈現(而小程式正好,沒提供類似 WebView 的客戶端控制元件)。比如有大量的內容網站,其文章內容都是儲存為一個 HTML 片段,無法直接呈現在小程式中。如果需要展示,一個思路是構建中間服務,將 HTML 轉譯成一種更簡單利於渲染的中間格式資料,然後,在小程式端把中間格式的資料轉換成小程式的標籤進行呈現。我們在做“輕芒生活”的時候,正好設計並實現了一個轉義服務,將任意一個 HTML 頁面轉換成中間格式(內部名是 RAML),解決了內容性 HTML 頁在小程式上的呈現問題,如圖 1 所示。

圖 1   在小程式中呈現 HTML 內容頁
圖 1 在小程式中呈現 HTML 內容頁

和 HTML 相比,小程式的 WXSS 算是比較完整地保留了 CSS 的特徵,這一點還蠻出乎意料。WXSS 在語義上最大的不同,一是在於它支援了相對尺寸單位 rpx(responsive pixel),每 750rpx 等價於當前裝置的螢幕寬度,它的引入,把那種繁複的螢幕尺寸適配變得簡單了不少。而和 CSS 的另一個不同是它更像傳統控制元件樣式用法,不支援 CSS3 那麼多的選擇器,使用中更多的是一個控制元件一個 class。

小程式中雖然支援 ES6 標準的 JavaScript,但視窗級的 JavaScript 卻完全被廢棄掉了,開發者無法用 JavaScript 去呼叫 window、document 物件來修改介面元素完成邏輯。小程式中的 JavaScript 其實直接對應 Node.js 的用法,用來完成後臺業務邏輯,而不是直接控制互動。小程式的這個設計,使其可以用到 Virtual Dom 的方式來渲染介面,讓介面資料更新時的效能優化成為可能,但付出的代價就是少了視窗級 JavaScript 的那層膠水黏合,使得很多功能的開發變得極其呆板和繁複。

互動如何傳導

所謂互動的傳導,是當用戶和介面發生互動時,平臺框架通過何種方式告訴業務層,並將處理後的變化呈現回交互介面上。如果把 WXSS + WXML 繪製的頁面看成“前端”,把 JavaScript 撰寫的業務邏輯看成“後端”,你會發現,小程式的前後端互動特別像 Web 1.0 的模式,前端把互動行為封裝成事件(event)傳送到後端,後端處理完成後,通過 setData 方法將資料回傳到前端,如圖 2 所示。

圖 2  小程式的互動傳導
圖 2 小程式的互動傳導

小程式提供的 Events,基礎的有類似單擊、長按、觸控、滑動等,對於視訊播放器等控制元件,還有監聽播放、暫停等。這些事件比較基礎,沒有更高階的手勢、多點觸控等相關事件,但也還足夠讓開發者具體瞭解使用者的輸入,進而做出響應。 而小程式給介面響應的唯一方式,是通過 Page 中的 setData API 對介面上的資料進行更新,小程式會比較兩次呼叫期間資料的變化,來決策需要更新哪部分的互動介面。

舉個實際的例子,假設開發者需要做一個滑動切換頁面的效果,在小程式中該如何實現?首先,是將變數資料引入渲染頁面:

<view class="page" id="current-page" 
        style="left:{{distance}}rpx;"
        bindtouchstart="movePage" bindtouchcancel="movePage"
        bindtouchmove="movePage" bindtouchend="movePage">
</view>

可以看到,distance 是一個模版引數,它初始值為 0,表示移動的距離。通過 bindtouchstart 等函式繫結上 JavaScript 的方法,將事件回傳。

movePage: function(event) {
    var status = {
        needUpdate: false,
        distance: 0
    }
    // 處理各種事件,計算是否需要重新整理,和移動方向
    if ("touchstart" === event.type) {
        // 開始計算移動
        ...
    } else if ("touchend" === event.type) {
        // 判定移動的距離是否足夠.
        ...
    } else if ("touchcancel" === event.type) {
        // 被打斷就算了.
        ...
    } else if ("touchmove" === event.type) {
        // 計算移動距離
        ...
    }
    // 根據移動的距離,來更新介面
    if (status.needUpdate) {
        this.setData({
            distance: status.distance
        })
    }
}

而在 JavaScript 一端,則捕獲事件、計算偏移量,然後將新的偏移量送到前端介面。

從這裡可以看到,小程式的互動是典型的單向模式,前端回傳事件,資料單向地推到前端,而不是通過類似“變數”、“狀態”等方式來告知。這樣的模式下,開發者對介面變化的控制往往不可能太精準,整個核心都依賴於小程式對兩次資料變化的 diff 計算,這將會最終影響整個互動的效能。

小程式開發模式的特點

至此,我們可以來總結一下小程式開發的一些特點了。整體來看,小程式是借了 HTML5 的技術棧,行了傳統客戶端開發的模式,這一點和 React 等平臺會比較相近,可以視為 HTML5 的一個新分支。

從設計思路看,小程式做了大量的“限制”,最大的限制是開發者其實無法通過 JavaScript 這樣的程式語言直接對介面進行控制,而是通過資料驅動來間接實現。這對於缺少開發經驗的人而言,是有益的事情,因為降低了理解的門檻,但對於複雜的應用來說,這個模式開發起來比較呆板,往往是一個變化多處修改,增加了理解程式碼的成本。

開發小程式的坑

開發小程式的日子,也是一個踩坑的歷程。簡單總結,小程式中的坑大概來自這幾個方面:

  • Web 相容性。小程式引入了 HTML/CSS 作為技術棧,並在其基礎上進行了定製。很多開發中的問題都來自於“定製”,因為你並不知道哪部分是被定製,哪部分是被繼承了。比如,你用了一個 CSS 語法,發現並不生效,或者效果和瀏覽器中的不一樣,於是,只能換一個寫法,結果很有可能又會繼續發現,這個新的寫法可能效果也不對,於是只能繼續嘗試,如此反覆,可能會消耗大量的時間。
  • 開發環境不穩定。小程式的開發,是基於微信自制的 IDE,但當下,IDE 的穩定性、易用性都非常差,時常出現 Bug,你以為是程式寫錯了,但其實,是 IDE 的 Bug,重啟一下 IDE,一切都迎刃而解了。於是,當你日後開發小程式時出現某種異樣,先重啟 IDE,再看問題還在不在,也許是種更節省時間的方式。
  • 缺少真機除錯環境。小程式的執行時其實就是微信,微信幾乎沒提供任何真機上的除錯工具(也不能說完全沒有,有一個只能在真機上瞪著眼睛看的日誌框)。在模擬器中除錯好的程式,可能在真機上執行起來並不如預期。比如,我們碰到過真機上白屏、位置錯亂、動畫效果不對,以及 Android 上至今還不能執行等問題。這對於稍微複雜的程式而言,頗為夢魘,想做一些細粒度的調整和優化,基本只能靠猜。
  • 閉源且缺少學習資料。小程式整體上是閉源狀態(雖然模擬器和 IDE 部分可以通過反編譯來看),且缺少足夠的學習資料。如果一旦碰到控制元件如何使用、為什麼這麼用不對之類的問題,就只能靠不停地試來解決,也需要耗費大量時間。

簡而言之,作為一個新的開發平臺,微信小程式從本身的穩定性,以及配套的工具鏈上都不算完善。對於早期開發者而言,需要耗費額外的精力去嘗試和探索,但這也許就是一個新平臺的價值和代價吧。

文章來源:http://geek.csdn.net/news/detail/133497

相關推薦

程式程式設計式路由跳轉

頁面棧表現方式 路由方式 頁面棧表現 初始化 新頁面入棧 開啟新頁面 新頁面入棧 頁面重定向 當前頁面出棧,新頁面入棧

程式程式設計模式

作者簡介: 範懷宇,輕芒聯合創始人,畢業於清華大學,前豌豆莢技術負責人,專注於移動開發十餘年,曾出版《Android 開發精要》。愛研習好程式碼和設計,相信好的產品能改變生活,好閱讀樂分享。 責編:唐小引,技術之路,共同進步。歡迎技術投稿、給文章糾錯,請傳送郵件至[ema

程式開發的三種模式

摘要:截止到2018年6月底,正式上線釋出的微信小程式已超過100萬個。而越來越多的公司也已經在做微信小程式開發,許多人會覺得“微信小程式開發是開發者們的專利”。答案是否定的,今天意公子帶大家瞭解微信小程式開發的三種模式,其實技術小白也能輕鬆製作。 做微信小程式開發,主要的三種

程式非同步API為Promise簡化非同步程式設計

把微信小程式非同步API轉化為Promise。用Promise處理非同步操作有多方便,誰用誰知道。 微信官方沒有給出Promise API來處理非同步操作,而官方API非同步的又非常多,這使得多非同步程式設計會層層回撥,程式碼一複雜,回撥起來就想砸電腦。 於是寫了

智慧程式開發3大益處與盈利模式

現在小程式已經成為了一種潮流,很多人都覺得智慧微信小程式好,但是如果你具體問他小程式好在哪裡?小程式開發的作用是什麼?要如何實現盈利的話,很多人都並不清楚這些問題,對此,今天人人有站喆哥就和大家聊聊發小程式有哪些作用? 1、吸引更多的新使用者 智慧微信小程式可以吸引到很多的新客戶,

程式-多層餅圖/包含關係餅圖/自定義餅圖關係模式

效果圖如下 WXML <view class='chart_wrapper'> <view class='chart_wrapper'> <view class='chart_mark'> <view class

(六)程式:image元件的4種縮放模式與9種裁剪模式, 和靜態多文章列表

4種縮放模式 scaleToFill 不保持縱橫比例縮放圖片,使圖片的高度完全拉伸至填滿image元素         此模式是縮放的預設模式,預設時,小程式以此模式來縮放圖片 aspectFit 保持縱橫比縮放圖片,使圖片的長邊能完全顯示出來&nbs

程式使用async/await函式進行非同步程式設計

早些時候,研究了一下前端非同步程式設計,想著使用async/await函式編寫非同步程式碼,簡直爽的不要不要的,而我本身是做小程式開發的,所有自然希望能夠讓async/await函式在小程式中大展拳腳了,這裡就簡單介紹一下如何在微信小程式中使用async/await函式來編寫非同步程式碼。 微信

程式 關閉除錯模式後顯示載入中

踩坑小記 微信小程式無論是開發版還是體驗版,開啟除錯模式一切都OK,但關閉後就一直顯示載入中??? 1.wx.request呼叫的伺服器地址不能含有埠號; 2.獲取openid的時候一定要記得請求伺服器,伺服器請求並返回openid; 踩坑小計

絕對乾貨:程式有哪些模式能夠讓你快速盈利?

今年是小程式的爆發元年,火爆程度可想而知。從1月份公開課資料爆出後,引發國內震驚,發展至今小程式也越來越成熟,現在日活已經3億使用者,上線超過200萬小程式,這些絕不是運氣索然。那麼小程式盈利模式有哪些呢? 一、小程式創業 對現有產品的功能進行延伸,開發一個與現有ap

WxMasonry程式瀑布流佈局模式

效果 github地址 先提一個問題,以免你們不看到最後 在微信小程式的迴圈列表中,如何實現圖片的等比例縮放,這件事上我有嘗試,但是效果不佳,歡迎交流解決方案!! 實現方式 雖然實現方式很簡單,但是我起初沒有想到,也是繞了很遠的路才想到。當你看到下面的解決方案的

程式之除錯模式

“Console”:小程式的除錯控制檯;“Wxml”:和檢視html頁面結構類似;“Sources”:顯示專案的指令碼檔案;“Appdata”:檢視專案的資料情況;“Storage”:儲存器視窗(用於顯示專案在使用wx.setStorage介面或者wx.setStorageS

程式--投票程式設計與實現(圖片、視訊釋出、分組、稽核、排名)

### 投票微信小程式設計與實現(圖片、視訊釋出、分組、稽核、排名) ​ 之前接到一個需求,設計一個類似H5 投票系統之類的小程式,我絞盡腦汁,冥思苦想,最後終於做了出來。 再次感謝 @文曉港 的`ColorUI`微信樣式元件庫,實在是開發者的好幫手。秉持開源精神,該小程式程式碼已**全部開源**。後臺使

程式 藍芽 長資料包 分包拆包

https://www.jianshu.com/p/de7bd0093c43 關於 微信小程式藍芽 分包傳送 及 多包傳送 不返回問題   關於分包傳送 20位元組分包,微信小程式支援多於20位元組傳送。但是低功耗藍芽傳輸可能會有問題,建議分包傳送   for

程式登入授權

wxml檔案內容 <view class="container"> <view class="userinfo"> <button wx:if="{{!hasUserInfo && canIUse}}" open-type="getUserInf

程式需求IIS伺服器配置https關於SSL,TLS的綜合解決方案

1.伺服器安裝證書:必須確保證書是sha256RSA簽名演算法的,反正sha1是肯定出問題。 2.為了保證小程式在IOS上正常執行,必須保證伺服器的TLS為1.2及以上版本,下面網址可以測試你伺服器的證書等情況:  https://www.ssllabs.com/ssltes

程式之物流狀態時間軸

一個月左右沒更新部落格了,最近有點懶了哈(工作上真的忙),很多工作上學習到的東西都沒有及時分享出來,有點愧疚,不過自己最近一直在收集資料和學習一些新技術,最主要是想要構建自己的前端技術體系和自定義一個前端規範文件,哈哈哈。說重點啦,微信小程式裡面開發的商城模組還挺多的,剛好寫了一個物流狀態的時間軸,簡單分享一

程式登陸 —— 程式教程系列(20)

簡介: 微信登陸,在新建一個微信小程式Hello World專案的時候,就可以看到專案中出現了我們的微信頭像,其實這個Hello World專案,就有一個簡化版的微信登陸。只不過是,還沒有寫入到咱們自家的後臺中而已。 新建一個Hello World專案,找到a

第三方(程式)連線OneNET平臺

前言 一方面是個課設,另一方面專案組有點需求,順便就把提高部分做了。主要用的微信小程式來作為展示介面以及控制介面,以及使用了OneNET平臺連線硬體。 因為硬體部分不是我擅長的,所以這邊就直接燒了例程,稍微改改。所以在本文中硬體平臺就簡寫了。 硬體平臺 說明 先說硬體

APP與程式的區別

自微信小程式問世以來.很多人都在問一個問題:微信小程式跟APP有什麼不同之處,其實看似簡單的問題,回答起來比較複雜,雖然兩者都屬於移動營銷,下面水滋源來具體談談微信小程式和APP區別的一些內容。 小程式: 是一種依託在微信作為平臺執行的程式也是不需要安裝即可使用的應用。實現用完即走的理念