↓↓(全网最稳定Webstorm激活码)↓↓

(上网址输入到浏览器即可下载)

-

正文

前言

前段时间由于要实现 H5 移动端拉取微信卡包并同步卡包数据的功能,于是在项目中引入了**`微信 JS-SDK(jweixin)`**[1]相关包实现功能,但也由此让我对其产生了好奇心,于是打算好好了解下相关的内容,通过查阅相关资料发现这其实属于JSBridge的一种实现方式。

因此,只要了解JSBridge就能明白微信 JS-SDK是怎么一回事。

js打开新的页面_打开页面就执行js_js 打开页面自动跳转

66A4AF0E.jpg为什么需要 JSBridge?

相信大多数人都有相同的经历,第一次了解到关于JSBridge都是从微信 JS-SDK(WeiXinJSBridge)开始,当然如果你从事的是Hybrid 应用或React-Native开发的话相信你自然(应该、会)很了解。

其实JSBridge早就出现并被实际应用了,如早前桌面应用的消息推送等,而在移动端盛行的时代已经越来越需要 **JSBridge**,因为我们期望移动端(Hybrid 应用或React-Native)能做更多的事情,其中包括使用客户端原生功能提供更好的 交互 和 服务 等。

然而JavaScript并不能直接调用和它不同语言(如 Java、C/C++ 等)提供的功能特性,因此需要一个中间层去实现JavaScript与其他语言间的一个相互协作,这里通过一个Node架构来进行说明。

Node 架构

js打开新的页面_js 打开页面自动跳转_打开页面就执行js

核心内容如下:

中间层 Node Bindings

底层 V8 + libuv

这里不难发现Node Bindings就有点类似JSBridge的功能,所以JSBridge本身是一个很简单的东西,其更多的是一种形式、一种思想。

为什么叫 JSBridge?

Stack Overflow 联合创始人Jeff Atwood在 2007 年的博客《The Principle of Least Power[2]》中认为“任何可以使用 JavaScript 来编写的应用,并最终也会由 JavaScript 编写”,后来 JavaScript 的发展确实非常惊人,现在我们可以基于 JavaScript 来做各种事情,比如 网页、APP、小程序、后端等,并且各种相关的生态越来越丰富。

作为 Web 技术逻辑核心的JavaScript自然而然就需要承担与其他技术进行『桥接』的职责,而且任何一个移动操作系统中都会包含 运行JavaScript的容器环境,例如WebView、JSCore等,这就意味着 运行 JavaScript 不用像运行其他语言时需要额外添加相应的运行环境。

JSBridge应用在国内真正流行起来则是因为微信的出现,当时微信的一个主要功能就是可以在网页中通过JSBridge来实现内容分享。

JSBridge 能做什么?

举个最常见的前端和后端的例子,后端只提供了一个查找接口,但是没有提供更新接口,那么对于前端来讲就是再想实现更新接口,也是没有任何法子的!

同样的,JSBridge 能做什么得看原生端给 JavaScript 提供调用 Native 什么功能的接口,比如通过微信 JS-SDK网页开发者可借助微信使用拍照、选图、语音、位置等手机系统的能力,同时可以直接使用微信分享、扫一扫、卡券、支付等微信特有的能力。

JSBridge作为JavaScript与Native之间的一个桥梁,表面上看是允许 JavaScript 调用 Native 的功能js打开新的页面,但其核心是建立Native和非 Native间消息双向通信通道。

打开页面就执行js_js打开新的页面_js 打开页面自动跳转

双向通信的通道:

Native 向 JavaScript 发送消息:

JSBridge 是如何实现的?

JavaScript 的运行需要 JS 引擎的支持,包括Chrome V8、Firefox SpiderMonkey、Safari JavaScriptCore等,总之JavaScript 运行环境是和原生运行环境是天然隔离的,因此,在JSBridge的设计中我们可以把它类比成JSONP的流程:

JSBridge实现 JavaScript 调用的方式有两种,如下:

在开始分析具体内容之前,还是有必要了解一下前置知识WebView。

WebView 是什么?

WebView是 原生系统 用于移动端 APP嵌入Web的技术,方式是内置了一款高性能webkit内核浏览器,一般会在 SDK 中封装为一个WebView组件。

WebView具有一般View的属性和设置外,还对url进行请求、页面加载、渲染、页面交互进行增强处理,提供更强大的功能。

WebView 的优势在于当需要更新页面布局或业务逻辑发生变更时,能够更便捷的提供 APP 更新:

微信小程序中的 WebView

小程序的主要开发语言是JavaScript,其中逻辑层和渲染层是分开的,分别运行在不同的线程中,而其中的渲染层就是运行在WebView上:

运行环境逻辑层渲染层

iOS

JavaScriptCore

WKWebView

安卓

V8

chromium 定制内核

小程序开发者工具

NWJS

Chrome WebView

js 打开页面自动跳转_js打开新的页面_打开页面就执行js

6F98DD16.jpg

在开发过程中遇到的一个坑点就是:

JavaScript 调用 Native — 实现方案一

通过 JavaScript 调用 Native 的方式,又会分为:

【 注入 API 】

核心原理:

这里不通过iOS的UIWebView和WKWebView注入方式来介绍了,感兴趣可以自行查找资料,咱们这里直接通过**微信 JS-SDK**[3]来看看。

打开页面就执行js_js 打开页面自动跳转_js打开新的页面

6A9DCAFF.gif

当通过的方式引入JS-SDK之后,就可以在页面中使用和微信相关的 API,例如:

// 微信授权
window.wx.config(wechatConfig)

// 授权回调
window.wx.ready(function () {...})

// 异常处理
window.wx.error(function (err{...})

// 拉起微信卡包
window.wx.invoke('chooseInvoice', invokeConf, function (res{...})
复制代码

如果通过其内部编译打包后的代码(简化版)来看的话,其实不难发现:

!(function (e, n{
  'function' == typeof define && (define.amd || define.cmd)
    ? define(function () {
        return n(e)
      })
    : n(e, !0)
})(thisfunction (e, n{
   ...
   function i(n, i, t) {
    e.WeixinJSBridge
      ? WeixinJSBridge.invoke(n, o(i), function (e{
          c(n, e, t)
        })
      : u(n, t)
   }
   
   if (!e.jWeixin) {
    
    var N = {
        config(){
          i(...)
        },
        ready(){},
        error(){},
        ...
    }
    
    return (
      S.addEventListener(
        'error',callback1,
        !0
      ),
      S.addEventListener(
        'load',callback2,
        !0
      ),
      n && (e.wx = e.jWeixin = N),
      N
    )
  }
})
复制代码

【 劫持 URL Scheme 】URL Scheme 是什么?

URL Scheme是一种特殊的URL,一般用于在Web端唤醒App(或是跳转到App的某个页面),它能方便的实现App间互相调用(例如 QQ 和 微信 相互分享讯息)。

URL Scheme的形式和普通 URL(如:****)相似,主要区别是protocol和host一般是对应APP自定义的。

通常当App被安装后会在系统上注册一个 **自定义的 URL Scheme**js打开新的页面,比如weixin://这种,所以我们在手机浏览器里面访问这个scheme地址,系统就会唤起对应的App。

例如,当在浏览器中访问weixin://时,浏览器就会询问你是否需要打开对应的APP:

劫持原理

Web端通过某种方式(如iframe.src)发送URL Scheme请求,之后Native拦截到请求并根据URL Scheme和携带的参数进行对应操作。

例如,对于谷歌浏览器可以通过chrome://version/、chrome://chrome-urls/、chrome://settings/定位到不同的页面内容,假设跳转到谷歌的设置页并期望当前搜索引擎改为百度,可以这样设计chrome://settings/engine?changeTo=baidu&callbak=callback_id:

以上只是一个假设哈,并不是说真的可以这样去针对谷歌浏览器进行修改,当然它要是真的支持也不是不可以。

是不是感觉确实和JSONP的流程很相似呀 ~ ~

【 弹窗拦截 】

弹窗拦截核心:利用弹窗会触发WebView相应事件来实现的。

一般是在通过拦截Prompt、Confirm、Alert等方法,然后解析它们传递过来的消息,但这种方法存在的缺陷就是iOS中的UIWebView不支持,而且iOS中的WKWebView又有更好的scriptMessageHandler,因此很难统一。

Native 调用 JavaScript — 实现方案二

Native调用JavaScript的方式本质就是执行拼接JavaScript字符串,这就好比我们通过eval()函数来执行JavaScript字符串形式的代码一样,不同的系统也有相应的方法执行JavaScript脚本。

Android

在Android中需要根据版本来区分:

安卓 4.4 以上版本使用evaluateJavascript()

webView.evaluateJavascript("javascript:foo()"null);
复制代码

IOS

在IOS中需要根据不同的WebView进行区分:

最后

以上通过微信 JS-SDK到JSBridge的一个简单介绍,大家现在应该不至于认为JSBridge是一个高大上、深不可测的东西了,毕竟其核心思想是清晰明了的,而且本质上还是需要强依赖于原生端的具体实现。

希望本文对你有所帮助!!!