技術點總有它的來由。javascript
文章概要:css
⑴.什麼是hybrid?html
hybrid即「混合」,前端和客戶端的混合開發模式,某些環節也可能涉及到 server 端。 hybrid 底層依賴於Native提供的容器(WebView),上層使用html&css&JS作業務開發。前端
⑵.webview是什麼?java
app中的一個組件,相似於小型瀏覽器內核。native提供的容器盒子,用於加載h5頁面。ios
(3).hybrid存在的意義?git
能夠快速迭代開發更新。(無需app審覈,哈哈由於對手機的操做權限不高?,相對於app)github
hybrid開發效率高,低成本,跨平臺,ios和安卓共用一套h5代碼。(ios和安卓接口一致)web
hybrid從業務開發上講,沒有版本問題,有BUG能及時修復(相對於app)。chrome
native提供的容器盒子,用於加載h5頁面,那麼h5的頁面要怎麼跟native交互?
前端和客戶端的交互大概描述:
前端的頁面跟native交互,是經過schema協議。(事實上Native能捕捉webview發出的一切請求,這個協議的意義在於能夠在瀏覽器中直接打開APP)
⑴.什麼是schema協議?
大概描述 :scheme是一種頁面內跳轉協議,經過定義本身的scheme協議,native 攔截這個請求,能夠很是方便跳轉app中的各個頁面。
經過執行如下操做支持自定義URL方案:
一些URL Scheme
https://www.zhihu.com/question/19907735
截取一端代碼,代碼來源:https://github.com/tcoulter/jockeyJS/blob/master/JockeyJS/JS/jockey.JS
// 這段代碼主要功能是前端經過一個特殊的協議給客戶端發消息,客戶端攔截請求而後處理 dispatchMessage: function(type, envelope) { // We send the message by navigating the browser to a special URL. // The iOS library will catch the navigation, prevent the UIWebView // from continuing, and use the data in the URL to execute code // within the iOS app.
var src = "jockey://" + type + "/" + envelope.id + "?" + encodeURIComponent(JSON.stringify(envelope)); var iframe = document.createElement("iframe"); iframe.setAttribute("src", src); document.documentElement.appendChild(iframe); iframe.parentNode.removeChild(iframe); iframe = null; }
⑵.具體H5與Native通訊,JS to native?
JS與Native通訊通常都是建立這類URL被Native捕獲處理。
⑶.native到h5頁面,native to JS?
native提供的容器盒子那麼native,能否調用它提供的webview中window對象的方法了?
native 能夠 調用以前跟前端約定好的掛載在window對象上面的方法。(具體實現了?)
/ Send an event to JavaScript, passing a payload. // payload can be an NSDictionary or NSArray, or anything that is serializable to JSON. // It can be nil. [Jockey send:@"event-name" withPayload:payload toWebView:webView]; // If you want to send an event and also execute code within the iOS app when all // JavaScript listeners have finished processing. [Jockey send:@"event-name" withPayload:payload toWebView:webView perform:^{ // Respond to callback. }];
前端與Native兩種交互形式:
① URL Schema(前端先定義對象,以及交互方法)
② 客戶端定義對象,注入全局變量(Android自己就支持相似的實現,因此此處討論ios的JavaScriptCore )
JavaScriptCore是一個C++實現的開源項目。使用Apple提供的JavaScriptCore框架,能夠在Objective-C或者基於C的程序中執行Javascript代碼,也能夠向JavaScript環境中插入一些自定義的對象。JavaScriptCore從iOS 7.0以後能夠直接使用,資料:https://developer.apple.com/documentation/javascriptcore。
⑴.URL Schema(前端先定義對象,以及交互方法)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1"> <title>Document</title> </head> <body> <button id="btn1">掃一掃</button> <script type="text/javascript"> function send(type, payload,callback) { var envelope = { id: id, type: type, host: host, payload: payload }; window.myapp.[envelop.id] = callback; var src = "myapp://"+envelope.id + "?" + encodeURIComponent(JSON.stringify(envelop)); //告訴客戶端此時調用的函數, 函數執行完成後,告訴h5執行window.myapp.[envelop.id]這個函數。
// host 加入使得客戶端更容易控制是否響應和處理(畢竟app內可能有需求內嵌第三方頁面)
var iframe = document.createElement("iframe"); iframe.setAttribute("src", src); document.documentElement.appendChild(iframe); iframe.parentNode.removeChild(iframe); iframe = null; } document.getElementById('btn1').addEventListener('click', function () { send("scan", {}, (payload) => { console.log("hi") }) }) </script> </body> </html>
一般代碼實現會把send函數部分進行封裝,前端只須要實現與native約定的功能函數。
getPort: function() { window.send("getPort", {}, (payload) => { }); }, login: function(args = {}) { window.send("login", args, (payload) => { }); },
⑵.客戶端定義對象,注入全局變量(客戶端注入全局變量,供h5使用)
// 頁面調用了未聲明方法,事實上是Native注入給window對象的。(native在本地實現了js方法並注入h5)
// 在頁面加載完成前注入全局變量myapp,myapp下面的方法,即app提供的API方法 myapp.getPort(data, (payload) => { }); myapp.login(data, (payload) => { });
兩種方式的區別,由客戶端仍是由h5預先定義對象,以及交互方法 。
代碼來源:https://github.com/tcoulter/jockeyJS/blob/master/JockeyJS/JS/jockey.JS(如下代碼例子,以URL Schema方式爲基礎)
⑴.導航欄的設置
導航欄一般是native實現,有回按鈕退防止頁面假死,即頁面卡死能夠回退。
同時native須要提供API供h5進行簡單的定製(好比有的須要關閉按鈕,分享按鈕,收藏按鈕等)
setBarBack() { Jockey.send("setBarBack", { "bar": { "position": "left", "cliekEvent": "onBack", } }); // 取消監聽onBack事件 Jockey.off('onBack'); // 監聽onBack事件 Jockey.on('onBack', () => { history.back() }); },
⑵.跳轉是Hybrid必用API之一,對前端來講有如下跳轉:
① H5跳轉Native界面
② H5新開Webview跳轉H5頁面。
用native的方法來跳轉,通常是爲了作頁面的動畫切換。
如圖咱們一般只會使用到導航欄下面部分,但咱們關注頁面的導航欄,H5端能夠註冊事件監聽native的導航欄的事件(非必須)
⑶.獲取基本信息
在具有用戶體系的模式下,H5頁面能從native拿到基本的登陸信息,Native自己就保存了用戶信息,提供接口給h5使用。
function getInfo() { return new Promise((resolve, reject) => { Jockey.send("getInfo", {}, (payload) => { }); }); },
⑷.調用native原生具有的功能
相機,手機頁面橫屏顯示或者豎屏顯示等。
⑸.關於調試
Android:輸入chrome://inspect/#devices便可(前提native打開了調試模式),固然Android也可使用模擬器,但與Android的真機表現過於不同,仍是建議使用真機測試。
iOS:需一臺Mac機,而後打開safari,在偏好設置中將開發模式打開,而後點擊打開safari瀏覽器,查看菜單欄開發菜單(前提native打開了調試模式)...
文章只是一個對hybrid的簡單瞭解,文中例子比較粗糙,理解不許確之處,還請教正。對於有興趣深刻了解Hybrid技術的設計與實現前端部分細節的能夠看看參考資料~~
參考資料:
http://www.cnblogs.com/yexiaochai/p/4921635.html