• js无法直接调用 app 的 API ,需要通过一种方式 —— 通称 js-bridge ,它也是一些js代码。当然,前提是 app 得开发支持,控制权在 app 端。就像跨域,server 不开放支持,客户端再折腾也没用。
  • 任何一个移动操作系统中都包含可运行 JavaScript 的容器,例如 WebView 和 JSCore。所以,运行 JavaScript 不用像运行其他语言时,要额外添加运行环境。因此,基于上面种种原因,JSBridge 应运而生
  • JSBridge 就像其名称中的『Bridge』的意义一样,是 Native 和非 Native 之间的桥梁,它的核心是 构建 Native 和非 Native 间消息通信的通道,而且是 双向通信的通道

JSBridge实现

方式1 - 注入 API

  • 客户端为 webview 做定制开发,通过webview提供的接口,向 JavaScript 的 Context(window)中注入对象或者方法,让 JavaScript 调用时,直接执行相应的 Native 代码逻辑,达到 JavaScript 调用 Native 的目的。

对于 iOS 的 UIWebView,实例如下:

JSContext *context = [uiWebView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];context[@"postBridgeMessage"] = ^(NSArray<NSArray *> *calls) {// Native 逻辑
};//前端调用方式
window.postBridgeMessage(message);

方式2 - 劫持 url scheme

  • 是一种类似于url的链接,主要区别是 protocol 和 host 一般是自定义的
  • 通过一个 iframe 请求 url
    • 为什么选择 iframe.src 不选择 locaiton.href ?因为如果通过 location.href 连续调用 Native,很容易丢失一些调用。
  • 如下方’my-app-name’ 是一个未识别的协议名称。既然未识别的协议,那就可以 app 监听所有的网络请求,遇到 my-app-name: 协议,就分析 path ,并返回响应的内容。
  • url 长度不够时,在 iOS 上采用了使用 Ajax 发送同域请求的方式,并将参数放到 head 或 body 里。这样,虽然规避了 url 长度的隐患,但是 WKWebView 并不支持这样的方式
  • 优点:
    • 支持 iOS6
const iframe1 = document.getElementById('iframe1')
iframe1.onload = () => {console.log(iframe1.contentWindow.document.body.innerHTML) // '{ version: '1.0.1' }'
}
iframe1.src = 'my-app-name://api/getVersion'
//微信的 scheme 以 'weixin://' 开头
//chrome://version 查看版本信息
//chrome://dino 恐龙小游戏

基于注入式封装sdk

  • native端不执行回调函数,只返回结果,所以需要发送方记录回调id,当结果返回时自己调用
(function () {var id = 0,//根据id存储的回调callbacks = {},//根据调用功能名称存储的回调registerFuncs = {};window.JSBridge = {// 调用 Nativeinvoke: function(bridgeName, callback, data) {// 判断环境,获取不同的 nativeBridgevar thisId = id ++; // 获取唯一 idcallbacks[thisId] = callback; // 存储 CallbacknativeBridge.postMessage({bridgeName: bridgeName,data: data || {},callbackId: thisId // 传到 Native 端});},//接收结果receiveMessage: function(msg) {var bridgeName = msg.bridgeName,data = msg.data || {},callbackId = msg.callbackId, // Native 将 callbackId 原封不动传回//如果需要回调native端,则需要记录native端本次的idresponstId = msg.responstId;// 具体逻辑// bridgeName 和 callbackId 不会同时存在if (callbackId) {if (callbacks[callbackId]) { // 找到相应句柄callbacks[callbackId](msg.data); // 执行调用}} elseif (bridgeName) {if (registerFuncs[bridgeName]) { // 通过 bridgeName 找到句柄var ret = {},flag = false;registerFuncs[bridgeName].forEach(function(callback) => {callback(data, function(r) {flag = true;ret = Object.assign(ret, r);});});//发送方执行回调后,回调native端if (flag) {nativeBridge.postMessage({ // 回调 NativeresponstId: responstId,ret: ret});}}}},//通过调用名称存储回调register: function(bridgeName, callback) {if (!registerFuncs[bridgeName])  {registerFuncs[bridgeName] = [];}registerFuncs[bridgeName].push(callback); // 存储回调}};
})();

基于scheme封装sdk

const sdk = {invoke(url, data, success, err) {const iframe = document.createElement('iframe')iframe.style.display = 'none'document.body.appendChild(iframe)iframe.onload = () => {const content = iframe.contentWindow.document.body.innerHTMLsuccess(JSON.parse(content))iframe.remove()}iframe.onerror = () => {err()iframe.remove()}iframe.src = `my-app-name://${url}?data=${JSON.string(data)}`}fn1(data, success, err) {invoke('api/fn1', data, success, err)}fn2(data, success, err) {invoke('api/fn2', data, success, err)}
}// 使用
sdk.fn1({a: 10},(data) => { console.log('success', data) },() => { console.log('err') }
)

Native 调用 JavaScript

  • 执行拼接 JavaScript 字符串,从外部调用 JavaScript 中的方法,因此 JavaScript 的方法必须在全局的 window 上。

JSBridge注入

由 Native 端进行注入

  • 注入方式和 Native 调用 JavaScript 类似,直接执行桥的全部代码
  • 优点在于:桥的版本很容易与 Native 保持一致,Native 端不用对不同版本的 JSBridge 进行兼容
  • 缺点是:注入时机不确定,需要实现注入失败后重试的机制,保证注入的成功率,同时 JavaScript 端在调用接口时,需要优先判断 JSBridge 是否已经注入成功

由 JavaScript 端引用

  • 直接与 JavaScript 一起执行。
  • 优点在于:JavaScript 端可以确定 JSBridge 的存在,直接调用即可;缺点是:如果桥的实现方式有更改,JSBridge 需要兼容多版本的 Native Bridge 或者 Native Bridge 兼容多版本的 JSBridge。

js-bridge原理相关推荐

  1. 浏览器原理-v8引擎-js执行原理

    浏览器原理-v8引擎-js执行原理 js简介 js应用: js的应用很广泛 可以应用于web,移动端,小程序,桌面应用,后端开发等 web开发包括(原生js,react,vue,angular等) 移 ...

  2. 图解WebGLThree.js工作原理【转】

    原文地址:https://www.cnblogs.com/wanbo/p/6754066.html 一.我们讲什么? 我们讲两个东西: 1.WebGL背后的工作原理是什么? 2.以Three.js为例 ...

  3. React.js核心原理实现:首次渲染机制

    2019独角兽企业重金招聘Python工程师标准>>> 一.前言 react.js和vue.js无疑是当下最火的js框架了,它们为组件式的开发传统前端页面.SPA页面.前后端分离等带 ...

  4. python闭包的原理_web前端:js 闭包原理

    闭包包含自由(未绑定到特定对象)变量;这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)."闭包"一词来源于以下两者的结合:要执行的代码 ...

  5. 模块化开发之sea.js实现原理总结

    seajs官网说:seajs是一个模块加载器,所以学习它并不难. 在我的理解就是:本来我们是需要手动创建 script标签 引入 js文件的,但用seajs后,它就自动帮我们完成这些工作. 这里只说实 ...

  6. js闭包原理与例子[转]

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.闭包原理: 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域 ...

  7. 图解WebGLThree.js工作原理

    "哥,你又来啦?" "是啊,我随便逛逛." "别介啊--给我20分钟,成不?" "5分钟吧,我很忙的." "不 ...

  8. V8引擎-js执行原理

    ​ 前言: 今天小编给大家讲解一下小伙伴们心中一直存在的问题,那就是我们在使用node环境或者浏览器的时候为什么可以执行js代码? 我们定义了很多的变量和函数内部是如何处理的? 以及我们常常说的作用域 ...

  9. NAT模式 桥接模式bridge原理理解

    桥接场景 无论现在的各种容器,还是我们之前常用的虚拟机,为了与局域网内其他IP通讯通常需要用到『桥接』. Bridge桥接方式 Bridge 将虚拟机桥接到host机器的网卡上,guest和host机 ...

  10. JS运行原理与机制(乾坤未定,你我皆是黑马4-5)

    上一篇讲的是js小游戏 实践了面向对象编程----------易于理解 我们记得小鸟.天空.管子就能记得这个游戏是怎么写出来的 js原理与运行机制 浏览器的渲染进程 进程与线程 进程是cpu资源分配的 ...

最新文章

  1. linux mysql内网_在Linux中mysql的一些基本操作
  2. AI加剧贫富分化不可避免,我们的职业会发生哪些变化?
  3. WebApi 的CRUD 的方法的应用
  4. fckeditor编辑器自定义加按钮菜单
  5. php mariadb 查询语法,从PHP调用的查询中的MySQL(MariaDB)执行超时
  6. [css] 请使用css写一个多级的下拉菜单
  7. JAVA 面试高频提问知识点之:SET、LIST 和 MAP 的区别
  8. 海王什么意思,海王是什么意思梗,网络流行词海王介绍
  9. js hasChildNodes()指针对元素节点子节点多个的话 true
  10. 目标检测(三) Fast R-CNN
  11. 2020最新 程序员数学(基础+进阶)
  12. 基于Leaflet 的Web地图客户端应用程序开发框架
  13. 解决端口占用问题 Port xxxx was already in use
  14. android前置拍照镜像代码,在Android中镜像前置摄像头
  15. android最新固件版本,Android获取系统(ROM)类别及版本号
  16. Python用tushare库获取股票数据批量存入mysql成功
  17. LeNet5—论文及源码阅读
  18. java - (二)netty 心跳监测机制
  19. 18118 勇者斗恶龙
  20. ORACLE学习详解

热门文章

  1. oracle table()函数
  2. spotify 缓存_如何组织您的Spotify库
  3. 典型相关分析介绍及python实现
  4. 一级减速器课程设计(说明书+CAD装配图、零件图)
  5. java 打印图片_java 实现打印(图片和文本)
  6. httpclient4 请一定设置超时时间
  7. ​Excel如何转换成Word文档?教你如何实现转换
  8. Linux转发性能评估与优化之——转发瓶颈分析与解决方案
  9. matlab打开dat形式文件_matlab的各种数据读取(txt,dat,mat等格式),文件打开关闭...
  10. 【Python3脚本分享】三个常用图片处理脚本(镜像处理,gif分解,多图合并)