當一切就緒後,就要開始進行API規劃,這一塊是整個Hybrid框架中很是重要的內容,畢竟對於前端頁面來講,只會經過JS API來調用功能。
基本上,API調用起來是否方便簡潔影響着整個體驗。前端
這裏將內容細分爲如下幾點:node
API約束(包括調用格式,傳參格式,回調格式)git
功能規劃(約定這個框架應該提供什麼樣的功能)github
權限校驗(很重要的一塊,校驗後才能調用,包括權限校驗的代碼格式,校驗一些什麼內容,以及哪些API無需校驗)web
模塊化的API(按照模塊劃分,每個模塊能夠做爲單獨的組件,便於拓展)api
其它優化(如在PC端調試API的頁面,部分API支持Promise等)微信
API調用關乎着整個體驗,咱們約定全部API統一採用以下調用方式websocket
quick.模塊名.方法({ 參數1: "", 參數2: "", success: fucntion(result) { // 成功回調 }, error: fucntion(error) { // 失敗回調 } });
約束說明框架
全部接口都爲異步調用異步
接收一個object
類型的參數
成功回調success
經過result
獲取成功數據
回調函數的觸發時機由具體的API決定,有的API是調用時便可回調(短時間),有的是某個事件觸發後才被回調(長期)
失敗回調error
,全部的API調用錯誤都會走失敗回調
混合開發框架最重要的一個功能就是__將原生功能以JS API形式提供給前端頁面調用__
本框架的API規劃以下:(這個項目中僅規劃了部分功能,實際使用中自行拓展便可)
quick |- ui // 系統ui組件 | |- toast | |- alert | |- confirm | |- prompt | |- showWaiting | |- closeWaiting | |- actionSheet | |- pickDate | |- pickTime | |- pickDateTime | |- popWindow |- page // 頁面(webview)管理 | |- open | |- openLocal | |- close | |- reload |- navigator // 導航欄控制 | |- setTitle | |- setMultiTitle | |- hookSysBack | |- hookBackBtn | |- setRightBtn | |- setLeftBtn | |- setRightMenu |- auth // 權限認證相關 | |- getToken |- device // 設備相關 | |- setOrientation | |- getDeviceId | |- getNetWorkInfo | |- getVendorInfo | |- closeInputKeyboard | |- vibrate | |- callPhone | |- sendMsg |- runtime // 運行環境 | |- launchApp | |- getAppVersion | |- getQuickVersion | |- getGeolocation | |- clearCache | |- clipboard | |- openUrl |- util // 其它工具 | |- scan | |- selectImage | |- cameraImage | |- selectFile | |- openFile
上述規劃的是最經常使用到的功能,具體每個API的介紹,傳入參數傳出參數等會在框架的API文檔中提到
若是整套框架要對外開放(如容許第三方按規範接入),那麼權限認證是必不可少的!
若是沒有權限認證?能夠想象下,隨便一個頁面就能調用任意API,獲取敏感信息。。。
那麼權限認證應該是怎樣的呢?根據不一樣需求,能夠劃分一個等級。
平臺級別的(像釘釘、微信這類對外開放的),須要配合後臺,有完整的受權,簽名,校驗機制
項目級別的(N個項目同一個框架,但業務各不相同),簡單的應用內部配置,直接校驗一些域名白名單信息便可
固然了,這個框架是後面的項目級別的,大批量的項目都採用的,所以直接簡單配置便可(示例中是在原生預留了這個入口,但沒有實現)
這裏暫不談具體實現(實現可參考源碼),只說說權限認證的流程:(如釘釘、微信中的)
quick.error(function(error) { // 處理錯誤 }); quick.config({ ... }); quick.ready(function() { // TODO: 處理驗證成功後的事情,例如調用api });
能夠看到,和其它框架同樣,前端也是config
,ready
,error
三步,
而後原生接收到config
時,內部進行校驗(校驗內容能夠是檢測頁面地址是否符合域名白名單等等...)
並且,若是config
失敗或者沒有校驗,那麼敏感API都沒法調用
無需校驗就可用的API
並非全部API都需校驗後才能用,咱們約定如下API默認就可用(這裏是一個粗糙的劃分,實際上能夠精確到每個API)
ui模塊的全部API page模塊的全部API navigator模塊的全部API
這樣作的好處是,若是不涉及到一些敏感數據,能夠無需校驗,提供效率(校驗若是規則畢竟重的話對速度仍是有影響的)
有一個全局變量quick
,但API並非直接綁定在全局變量下,而是按模塊劃分,譬如
quick.ui quick.device quick.page ...
這裏說明一下,用模塊化劃分,除了前端調用會更清晰外,原生進行API定義與組件API拓展時也更方便。
組件API的拓展機制
關於組件API的拓展機制,這裏也不具體描述如何實現(實現可參考源碼),僅說說大概是一個什麼樣的東西。
默認狀況下,框架會註冊如下組件(前面已經規劃的全部模塊)
ui page navigator auth device runtime util
可是假設某項目中忽然遇到了一個需求,要新增一個支付功能,而且要以API的形式提供給H5頁面調用,該如何實現呢?
注意,這個框架設計的初衷是能夠供N個項目使用,因此不可能全部的功能都集成進入框架中的,各個項目能夠拓展本身的組件
這時候就須要規劃這個拓展機制了,以下
// 1.前端config時,傳入須要註冊的組件別名 quick.config({ jsApiList: ['pay', 'speech'] });
// 2.原生框架中,接收到config後,基於傳入的別名,去對應項目配置文件中查詢路徑,而後將對應路徑的API實現類註冊 // 對應的組件的API實現類不是放框架中的,而是由各自的項目管理的,到時候框架就是一個固定的庫,給各個項目引用 // 代碼實現這裏省略 ...
// 3.前端中,經過一個固定的方法,調用剛註冊的組件API中的功能 quick.callApi({ name: 'xxx', mudule: 'pay', ... data: {}, success: function(result) {}, error: function(error) {}, });
經過這一套機制,能夠保持框架的可拓展性,就算應用不一樣的項目中,N多的功能,也能經過這種方法拓展,保持一致的使用
在大致功能都實現後,接下來還須要作一些優化功能,具體效果能夠是簡化調用,也能夠是方便調試
部分API支持Promise
前面定義的API中都是基於普通的回調進行的,在多層回調嵌套時仍然會畢竟麻煩,所以能夠拓展支持Promise調用方式
在拓展前,先定一個基調:全部短時間回調都支持Promise調用,長期回調不建議使用Promise
由於長期回調涉及到屢次回調(好比右上角按鈕),因此不建議使用Promise,若是強行要使用,這些API調用完畢後立刻就會進入then
具體實現參考源碼,這裏稍微對比下普通調用與Promise調用
quick.ui.alert({ title: '提示', message: 'sd#ddd測試', success: function(result) { console.log('點擊alert成功'); }, error: function(error) { console.error('失敗:' + JSON.stringify(error)); } });
quick.ui.alert({ title: '提示', message: 'sd#ddd測試', }).then(function(result) { console.log('點擊alert成功'); }).catch(function(error) { console.error('失敗:' + JSON.stringify(error)); });
上述還只是沒有嵌套的對比狀況,有嵌套時,區別更大
PC端調試API
相似於釘釘的調試頁面,這裏也規劃了一個在PC端調試API的頁面(基於websocket),後續會有更詳細的說明。
原理方面的源碼能夠先參考https://github.com/dailc/node-server-examples/tree/master/node-socketio-hybriddebug
能夠先預覽下效果
其它
其它優化後續再介紹
github
上這個框架的實現