【前端基础】Web与Native交互之The JSBridge FAQ(上)

简介: 今天我们来简单聊一下JSBridge

为什么要聊JSBridge?


好吧,JSBridge虽然也算比较古老了,但关于JSBridge的原理也是一个目前作为一名前端开发人员需要了解掌握的知识。


现如今,在做移动端H5开发时,少不了与Native之间进行交互,这里的Native,包括了传统意义上的App和现如今各种各样的坑王小程序们。 通常,各大公司都会封装一套自己的js sdk,用于提供给Web开发人员,来实现与Native之间的交互,他们可能有自己的名字,但他们统称为JSBridge


网上有很多介绍关于JSBridge原理的文章,充斥着大量OC 或Java代码,对于没有做过移动端Native开发但想了解JSBridge原理的同学来说都不是很友好。 所以,这篇文章主要就来给没有Native开发经验的同学们介绍一下H5页面在WebView中是如何通过JSBridge与Native进行交互的。同时,为了避免见到不必要的Native代码,这里不过多介绍通过JavaScriptCore API来实现交互的方式了,只介绍最初经典的方案。


什么是JSBridge?


简单的来说,JSBridge是一种H5页面与Native之间异步双向的通信的方式,它与我们日常接触到的最常见的HTTP这种通信方式,本质上没什么区别。


JSBridge存在的意义是啥?


为了生活变的更美好


为了体验更好


为了让用户分不清他用的到底是Web App还是Native App


为了效率


搞开发的嘛,肯定都是为了提高工作效率,同时不降低太多用户体验的情况下,复用,复用这个复用那个,统一这个统一那个的。一款App产品要做好几个端,重复的页面扔给H5算了!啥!需要一些奇特的功能?做个bridge接口吧!


JSBridge的通信过程是什么样的?



简单来说,这个通信过程与在餐厅吃饭时厨师上菜的流程类似,厨师一般不会亲自为你上菜(土豪私厨请忽略),厨师们每做好一道菜后就会按一下取餐铃,服务员听到铃声后就会过来取餐并为客人上菜。


通常情况下,按一下铃就会有服务员过来把菜取走,有些时候,厨师们可能同时做好了N道菜,按了N次铃,这时,服务员也会很敬业的将这些菜全部打包取走并处理。


那么它是如何实现的?


接下来该进入正题了,我们来看一下JSBridge的基本原理


  • 先从web 向 native发起通信开始:


前面我们了解到JSBridge的本质就是一种通信方式,所以,这里就比较容易理解了,H5调用Native的本质就是请求拦截


当H5的世界想与外面交流时,他只需要(也只能)发送一个请求,比如发送一个简单的GET请求即可。


我们会想到三种发请求的方式:


  1. 使用带有src属性标签发送请求,如iframe...


const iframe = document.createElement('iframe')
    iframe.src = "xxx"


这种方式也是各大Hybrid框架常用的方式,重复大量发送也不需要担心消息的丢失问题


  1. 使用location.href发送请求


location.href = "xxx"


这种方式比较适用于一些一次性调用的场景,例如H5中某个操作需要跳转至App的某一个页面,通过这种方式重复发送大量请求会造成请求消息的丢失,只接受最后一次。


  1. 使用Ajax的方式来发送请求


const url = 'xxx'
    fetch(url, { ... })
        .then()
        .catch()


这种方式写起来比较麻烦,但性能上略好于前两种


著名的Cordova.js使用的方式:


execIframe = document.createElement('iframe')
execIframe.style.display = 'none'
execIframe.src = 'gap://ready'
document.body.appendChild(execIframe)


iOS中的一个叫WebViewJavascriptBridge的库同样使用的是类似的方式:


const messagingIframe = document.createElement('iframe')
messagingIframe.src = 'https://__wvjb_queue_message__'
body.appendChild(messagingIframe)


注意到Cordova的src与下面的WebViewJavascriptBridge中的src不同的地方在于,Cordova使用了自定义URL Scheme的方式,嗯,这种方式用来唤起本地安装的App更常见些。


  • 需要带点参数


多数情况下,我们更希望给Native带一些参数过去,所以接下来,我们来看参数传递的问题


可能你会想到,在发送请求的时候直接把参数放在请求地址后面,通过query的形式拼接起来就可以了,比如像这样:


execIframe.src = 'gap://ready?p1=v1&p2=v2&p3=v3…'


但这种方式存在着一些问题


  • 首先,它的长度是有限的,虽然限制很长,但这终归会是一个隐患


  • 其次,如果是自己公司的App临时做一个jsbridge的接口,确实可以这样写,但是如果作为一个通用的工具来封装,这样去实现的话就与业务耦合的太紧密了。


在典型的JSBridge实现方案中,关于参数的处理是这样实现的:


  • 首先,任何时候,H5中JS需要调用Native时,发送请求的url是固定不变的,比如gap://ready


  • 其次,在window上定义一个全局的数组变量,名叫messageQueue,初始化时为空,当H5需要给Native发送消息时,先创建一个对象,并把所有相关的参数放在这个对象中,然后将这个对象插入messageQueue数组队尾,用代码来解释就是这样:


const messageQueue = []
window.messageQueue = messageQueue
messageQueue.push(JSON.stringify({
  message: 'xxx',
  params: 'xxx'
}))
// 发一个请求,按一下铃,戳一下Native~~
execIframe.src = 'gap://ready'


  • 当native收到gap://ready的请求后,就知道H5有新消息,就会执行一段神奇的代码,进入到WebView中,并将定义在window上的全局变量messageQueue数组中全部数据打包取走,并将messageQueue清空,取走后逐条解析执行。我们用eval函数来充当这段神奇的代码来解释这里的逻辑:


// 当Native拦截到'gap://ready'请求后执行的magic code
const messageQueue = eval('window.messageQueue')
const messages = JSON.parse(messageQueue)
for (const message in messages) {
     doSomeThingWithMessage(message)
}
eval('window.messageQueue = []')


这样,菜就被服务员端走了, 消息就被Native取走了


  • 接下来看看Native如何将处理结果告诉H5


如果餐厅的一个负责任的厨师需要让他的客户快要吃完一道前菜时告诉他,以便他去及时准备主菜,只需要在上菜时放上自己的名片,让客户快吃完的时候把厨师的名片交给服务员就可以了。


同样,如果H5需要Native执行完某一条指令时通知到H5,那么H5只需要在window上准备一个回调函数,在里面做该做的事,并将这个回调函数的名字在上一步创建消息对象时,放进这个对象中:


messageQueue.push(JSON.stringify({
  message: 'xxx',
  params: 'xxx',
  callBackName: 'xxx',
}))



相关文章
|
JavaScript 前端开发 Java
前端框架选择之争:jQuery与Vue在现代Web开发中的真实地位-优雅草卓伊凡
前端框架选择之争:jQuery与Vue在现代Web开发中的真实地位-优雅草卓伊凡
902 72
前端框架选择之争:jQuery与Vue在现代Web开发中的真实地位-优雅草卓伊凡
WEB端交互元件库:Axure设计师的高效利器
EQL UI是一款功能强大、组件丰富的Axure元件库,涵盖500+设计组件与完整后台模板,助力设计师高效搭建高保真原型,提升产品设计效率与质量。
1285 128
|
前端开发 JavaScript 安全
前端性能调优:HTTP/2与HTTPS在Web加速中的应用
【10月更文挑战第27天】本文介绍了HTTP/2和HTTPS在前端性能调优中的应用。通过多路复用、服务器推送和头部压缩等特性,HTTP/2显著提升了Web性能。同时,HTTPS确保了数据传输的安全性。文章提供了示例代码,展示了如何使用Node.js创建一个HTTP/2服务器。
526 3
|
移动开发 前端开发 JavaScript
前端web创建命令
本项目使用 Vite 搭建 Vue + TypeScript 开发环境,并基于 HTML5 Boilerplate 提供基础模板,快速启动现代前端开发。
286 2
|
JavaScript 前端开发 数据可视化
20.6K star!Excel级交互体验!这款开源Web表格神器绝了!
Handsontable 是一款功能强大的 JavaScript 数据表格组件,提供类 Excel 的交互体验。支持实时协作、数据绑定、公式计算等企业级功能,可轻松集成到 React/Vue/Angular 等主流框架。
3177 11
|
监控 前端开发 Java
构建高效Java后端与前端交互的定时任务调度系统
通过以上步骤,我们构建了一个高效的Java后端与前端交互的定时任务调度系统。该系统使用Spring Boot作为后端框架,Quartz作为任务调度器,并通过前端界面实现用户交互。此系统可以应用于各种需要定时任务调度的业务场景,如数据同步、报告生成和系统监控等。
915 9
|
缓存 JavaScript 前端开发
JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用
本文深入讲解了 JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用。
1212 5
|
JSON 前端开发 JavaScript
聊聊 Go 语言中的 JSON 序列化与 js 前端交互类型失真问题
在Web开发中,后端与前端的数据交换常使用JSON格式,但JavaScript的数字类型仅能安全处理-2^53到2^53间的整数,超出此范围会导致精度丢失。本文通过Go语言的`encoding/json`包,介绍如何通过将大整数以字符串形式序列化和反序列化,有效解决这一问题,确保前后端数据交换的准确性。
605 4
|
XML 前端开发 JavaScript
PHP与Ajax在Web开发中的交互技术。PHP作为服务器端脚本语言,处理数据和业务逻辑
本文深入探讨了PHP与Ajax在Web开发中的交互技术。PHP作为服务器端脚本语言,处理数据和业务逻辑;Ajax则通过异步请求实现页面无刷新更新。文中详细介绍了两者的工作原理、数据传输格式选择、具体实现方法及实际应用案例,如实时数据更新、表单验证与提交、动态加载内容等。同时,针对跨域问题、数据安全与性能优化提出了建议。总结指出,PHP与Ajax的结合能显著提升Web应用的效率和用户体验。
465 3
|
监控 前端开发 JavaScript
探索微前端架构:构建可扩展的现代Web应用
【10月更文挑战第29天】本文探讨了微前端架构的核心概念、优势及实施策略,通过将大型前端应用拆分为多个独立的微应用,提高开发效率、增强可维护性,并支持灵活的技术选型。实际案例包括Spotify和Zalando的成功应用。