技术点总有它的来由。文中例子参考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技术的设计与实现前端部分细节的能够看看参考资料~~
参考资料: