Hybrid APP 開發(六):JSSDK

拖稿了很久的「Hybrid APP開發系列」又更新了~
今天繼續寫JSSDKjavascript

爲何會有JSSDK

我以前文章介紹了經過 JSBridge 實現頁面和NA的相互調用,而且介紹了模板本地包的開發和後臺維護系統。今天介紹的是JSSDK,經過 JSSDK 能夠實現:前端

  1. 抹平JSBridge的平臺實現差別java

  2. 對齊端能力,內部消化版本差別node

  3. sdk封裝後的代碼更加符合前端習慣ios

  4. 權限控制、鑑權、對外開放,實現生態建設web

關於sdk的代碼級別的設計,能夠參考文章:《JSSDK設計指南chrome

若是作過微信頁面開發的,應該都知道 wx.js,這就是微信的JSSDK,在微信內須要調用微信的端能力就須要引入這個js。安全

JSSDK的設計

JSSDK的設計包括兩部分:微信

  1. 隨着每一個NA客戶端版本內置的js,稱爲: inject.js,他的主要做用是封裝JSBridge邏輯,經過隨版更新實現減小端能力的版本分裂,下降整個sdk的代碼複雜性。 inject.js是一段js代碼,當客戶端加載一個頁面的時候,由客戶端在適當的時機注入到webview內執行,執行後的代碼就會有給webview增長js方法,例如微信的 _WeixinJSBridge,類比chrome開發插件當中的 content_scripts,能夠在 document_startdocument_end等時機進行執行。app

  2. 雲端JS,即實際暴漏給開發者使用的js,稱爲: jssdk.js,這個是真正開發者使用的sdk文件,經過 script外鏈引入,例如 wx.js,這個js文件經過和 inject.js進行交換,完成端能力的調用、鑑權和客戶端事件監聽等操做


inject.js 和 jssdk.js工做機制

inject.js是客戶端和 jssdk的「翻譯官」,他接受頁面 jssdk的方法調用,將調用的命令解析成客戶端能夠理解的「語言」(JSBridge)而後傳給客戶端,同時當客戶端有事件/回調響應的時候,也經過 inject.js進行分發/回調。


舉例:NA分享能力

例如,客戶端實現了一個分享面板的UI組件,開放給web頁面能夠調用,這時候須要調用NA的端能力,JS須要將分享的:icon_url、title、content、link、type甚至訂製的NA面板信息等傳給NA,NA開始彈出這個面板,用戶進入NA層進行交互;

當用戶分享成功、失敗、取消等事件發生的時候,須要回調JS代碼,用戶由回到了web頁面,NA回調了JS callback,JS實現後續的邏輯。


jsbridge爲:

 
 
 
 
demoapp://share/dialog?title=三水清&link=http://js8.in&
複製代碼icon_url=xxx&content=我發現一個頗有用的前端公衆號複製代碼

inject.js代碼封裝以下:

 
 
 
 
;(function (window, document) {複製代碼function invoke (module, action, args, callback) {複製代碼let scheme = `demoapp://${module}/${action}?`複製代碼if (isFunction(args)) {複製代碼callback = args複製代碼args = null複製代碼}複製代碼// 處理下參數複製代碼if (isString(args)) {複製代碼scheme += args複製代碼} else if (isObject(args)) {複製代碼each(args, (k, v) => {複製代碼if (isObject(v) || isArray(v)) {複製代碼v = JSON.stringify(v)複製代碼}複製代碼scheme += `${k}=${v}`複製代碼})複製代碼}複製代碼// callback獨立傳,方便全局函數名命名複製代碼if (isFunction(callback)) {複製代碼var funcName = '_jsbridge_cb_' + getId()複製代碼window[funcName] = function () {複製代碼callback.apply(window, ([]).slice.call(arguments, 0))複製代碼}複製代碼scheme += (!~scheme.indexOf('?') ? '&' : '?') + `callback=${funcName}`複製代碼}複製代碼if (os.ios && versionCompare(os.version, '9.0') >= 0) {複製代碼window.location.href = scheme複製代碼} else {複製代碼var $node = document.createElement('iframe')複製代碼$node.style.display = 'none'複製代碼$node.src = scheme複製代碼var body = document.body || document.getElementsByTagName('body')[0]複製代碼body.appendChild($node)複製代碼setTimeout(function () {複製代碼body.removeChild($node)複製代碼$node = null複製代碼}, 10)複製代碼}複製代碼}複製代碼var $ = {複製代碼share: function (opts, callback) {複製代碼var defaultOpts = {複製代碼url: location.href,複製代碼title: '三水清',複製代碼content: '最好的前端公衆號',複製代碼icon_url: 'http://baidu.com/icon.png'複製代碼}複製代碼opts = Object.assign(defaultOpts, opts)複製代碼invoke('share', 'dialog', opts, callback)複製代碼}複製代碼}複製代碼window._InjectJS_ = $複製代碼}(window, document))複製代碼

jssdk.in代碼示例:

 
 
 
 
window.jssdk = {複製代碼share: _InjectJS_.share複製代碼}複製代碼

頁面調用:

 
 
 
 
jssdk.share({url: 'http://js8.in'}, (err, data) => {複製代碼if (!err) {複製代碼if (data.errno === 1) {複製代碼alert('失敗')複製代碼}else if (data.errno === 2) {複製代碼alert('取消')複製代碼}else {複製代碼alert(data.media) // 分享的平臺id,好比webxin_timeline複製代碼}複製代碼}複製代碼})複製代碼

這樣 jssdk調用 inject.js寫法,看似畫蛇添足,實則很巧妙,試想一下下面的場景:

  1. 客戶端某個版本分享能力升級,須要作兼容

  2. 某版本分享能力有bug,會引發crash,不能在此版本調用

  3. 分享成功以後的回調須要作鑑權,防止惡意刷分享行爲

  4. JSBridge有scheme調起換成jsinterface的調起(參考本系列JSBridge文章)

若是這些代碼都寫在 jssdk.js,那麼隨着版本的積累,代碼會愈來愈臃腫,而且全部版本的端能力都集中在 jssdk.js,很不利於管理,歷史的包袱也甩不掉。

inject.js的注入時機

由於 inject.js的設計機制,因此咱們但願 inject.js可以越早注入越好,這樣咱們在頁面head使用 jssdk.js 就不會找不到對象了!

咱們知道安卓WebView中能夠經過 webview.loadUrl("javascript:xxx」)的方式來調用js裏面的代碼,那麼,咱們也能夠利用 webview.loadUrl("javascript:xxx」);的方式來加載注入一段 js 代碼 。

安卓WebView 須要經過 webView.setWebViewClient(new MyWebClient());的方式來監聽網頁加載的各個週期方法回調,那麼咱們只須要在 onPageFinished(WebView view, String url) 中注入提早設置好的js 便可

在iOS中也有對應的時間點: webViewDidFinishLoaddidCreateJavaScriptContext

咱們可以找到的注入時機有限,爲了保證jssdk代碼在調用的時候,已經注入成功 inject.js,咱們只能實現相似 DOMContentLoaded這樣的 ready方法回調,使用jssdk的時候,所有寫在 jssdk.ready()內(相似 $(document).ready),當頁面 inject.js注入成功則拋出 ready事件,而後積累的事件棧依次出棧執行。

總結

本文介紹了hybrid開發中爲webview實現一個jssdk,介紹了 inject.js的注入時機, inject.js除了端能力的調用,還能夠和客戶端實現受權(如:微信的接入受權須要申請appid和token),同時還能夠針對全部的調起指令和回調進行安全校驗,屏蔽非法的調用和回調,本文只實現了最簡單的調用,這些高級的設計後面文章有機會再介紹,今天敲完收工搬家過節 :P

相關文章

@三水清
未經容許,請勿轉載。

掘金更新比公衆號晚一週左右。

感受有用,歡迎關注個人公衆號,最新文章第一時間看到!
相關文章
相關標籤/搜索