技术点总有它的来由。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