技術點總有它的來由。文中例子參考Jockeyjs.js容易理解一點。javascript
文章概要:css
hybrid即「混合」,前端和客戶端的混合開發模式,某些環節也可能涉及到 server 端。 hybrid 底層依賴於Native提供的容器(WebView),上層使用html&css&JS作業務開發。html
app中的一個組件,相似於小型瀏覽器內核。native提供的容器盒子,用於加載h5頁面。前端
能夠快速迭代開發更新。(無需app審覈,哈哈由於對手機的操做權限不高,因此無需審覈?)java
hybrid開發效率高,低成本,跨平臺,ios和安卓共用一套h5代碼。(ios和安卓接口一致)ios
hybrid從業務開發上講,沒有版本問題,有BUG能及時修復(相對於app)。git
native提供的容器盒子,用於加載h5頁面,那麼h5的頁面要怎麼跟native交互?github
前端和客戶端的交互大概描述:web
前端的頁面跟native交互,是經過schema協議。(事實上Native能捕捉webview發出的一切請求,這個協議的意義在於能夠在瀏覽器中直接打開APP)chrome
大概描述 :scheme是一種頁面內跳轉協議,經過定義本身的scheme協議,native 攔截這個請求,按需求處理,能夠很是方便跳轉app中的各個頁面。
經過執行如下操做支持自定義URL方案:
一些URL Scheme
截取一段代碼,代碼來源:github.com/tcoulter/jo…
// 這段代碼主要功能是前端經過一個特殊的協議給客戶端發消息,客戶端攔截請求而後處理
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;
}複製代碼
JS與Native通訊通常都是建立這類URL被Native捕獲處理。
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。
<!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) => {
});
},複製代碼
// 頁面調用了未聲明方法,事實上是Native注入給window對象的。(native在本地實現了js方法並注入h5)
// 在頁面加載完成前注入全局變量myapp,myapp下面的方法,即app提供的API方法
myapp.getPort(data, (payload) => {
});
myapp.login(data, (payload) => {
});複製代碼
兩種方式的區別,由客戶端仍是由h5預先定義對象,以及交互方法 。
代碼來源:github.com/tcoulter/jo…(如下代碼例子,以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()
});
},複製代碼
① H5跳轉Native界面
② H5新開Webview跳轉H5頁面。
用native的方法來跳轉,通常是爲了作頁面的動畫切換。
如圖咱們一般只會使用到導航欄下面部分,但咱們關注頁面的導航欄,H5端能夠註冊事件監聽native的導航欄的事件(非必須)
在具有用戶體系的模式下,H5頁面能從native拿到基本的登陸信息,Native自己就保存了用戶信息,提供接口給h5使用。
function getInfo() {
return new Promise((resolve, reject) => {
Jockey.send("getInfo", {}, (payload) => {
});
});
},複製代碼
相機,手機頁面橫屏顯示或者豎屏顯示等。
Android:輸入chrome://inspect/#devices便可(前提native打開了調試模式),固然Android也可使用模擬器,但與Android的真機表現過於不同,仍是建議使用真機測試。
iOS:需一臺Mac機,而後打開safari,在偏好設置中將開發模式打開,而後點擊打開safari瀏覽器,查看菜單欄開發菜單(前提native打開了調試模式)...
文章只是一個對hybrid的簡單瞭解,文中例子比較粗糙,理解不許確之處,還請教正。對於有興趣深刻了解Hybrid技術的設計與實現前端部分細節的能夠看看參考資料~~
參考資料: