Hybrid app本地开发如何调用JSBridge
前天同事问我公司内部的小程序怎么对接的,我回忆了一下,简单记录了一下前端同学需要注意的点。
背后还有小程序架构、网络策略等等。当时恰逢小程序架构调整,(老架构的时候我就发现了有一个问题点可以优化,但是跟那边人反馈之后,人家表示不要我管,新架构时发现这个问题还巧妙的遗留下来了)我虽然不负责那块,但是本着这样不优雅的原则,还是跟新架构的对接人讲了我的优化方案,讲明白了之后,同时上报各自直系领导,并建议我领导牵头开会推动。最后,无奈存量数据太多,老架构那边权衡之后决定不改动。(多说了几句,权当记录一下)
1、背景
公司研发的一款服务软件App(姑且称为“大地”),提供了包涵消息、待办、工作台、同事圈和通讯录五大功能模块,其中,工作台里集成了包括公司的移动客户端、PC端以及第三方平台的部分功能/服务(统称为“应用”)。
我今天要讲的是这个集成平台以什么方式展现“应用”,答案是:借鉴了微信的架构,自研了“小程序”接入“应用”。
我司小程序具有一种相对开放能力(面向全公司),赋能业务快速数字化、场景敏捷迭代,并且可在“大地”上便捷的获取和使用,同时具有完善的使用体验(这就是严格的接入审核标准带来的好处)。
在“大地”开发者平台,创建小程序会自动创建配套的公众号(公众号是为了推送消息使用,可订阅)。小程序开发不限制技术选型,开发完成之后按照小程序接入规范打包上架小程序,审核发布。
简单来说,可以把“大地”看成是一个“钉钉”,我现在要把我们的业务功能投放到“大地”上,就需要接入“大地”小程序,以小程序的方式在“大地”上为用户提供服务。
小程序架构:Cordova
框架做的WebView
,运行我开发的前端程序,通过Nginx
帮我把请求代理到微服务网关,由网关转发到目的主机处理请求。它虽然看上去是一个Native App
,但只有一个UI WebView
,里面访问的是一个Web App
,对我来说就是开发一个H5
应用调用一些所需的JSBridge
,也就是所谓的Hybrid App
。
下面看一下本地开发中的一些问题,以及我是怎么处理的
2、问题
Hybrid App
本地开发过程中没有真实的Native
环境的,同样也无法使用JSBridge
,这就会带来一个问题:跟原生交互的行为只能发布小程序才可以调试,本地玩不了,这...,相当fuck。
目的是想让本地开发同小程序测试环境具有相同的体验,我的想法是在本地模拟JSBridge
的方法,尽管不能带来真实的效果,至少触发了某个行为之后要有个反应,不至于让操作流程看起来像是“脱节”的(实际跟原生的交互行为并不多,比如:拍照、弹窗提示、定位等等)。
因此,我要做的就是本地模拟JSBridge
的一些方法,开发时触发了这些原生交互行为之后提示一些信息,等到上架小程序测试环境时,在手机上会用真实的JSBridge
方法自动替换掉我模拟实现的方法。
于是我就开始了下面的准备工作。
搞清楚
JSBridge
运行的原理本地模拟
JSBridge
的方法上架小程序是自动使用真实的
JSBridge
3、了解JSBridge
JSBridge:望文生义就是js
和Native
之前的桥梁,而实际上JSBridge
确实是JS
和Native
之前的一种通信方式。
简单的说,JSBridge
就是定义Native
和JS
的通信,Native
只通过一个固定的桥对象调用JS
,JS
也只通过固定的桥对象调用Native
。JSBridge
另一个叫法及大家熟知的Hybrid app
技术。
了解即可,更多的请参考
下图展示了JSBridge
的工作流程
上图中左侧部分正式我要做的,具体请看下文
看累了,三连一下,回看不迷路哟
3.1、我们的JSBridge
推测“大地”那边的JSBridge
应该是自己写的,没有初始化JSBridge
的操作
当调用JSBridge
时,必须在页面完全加载完成之后才能够拿到全局的JSBridge
,Cordova
框架提供deviceready
事件,该事件触发的时候表示全局的JSBridge
挂载成功。(注意:这就是我接下来操作的切入点,嘻嘻)
简单写下如下:
document.addEventListener('deviceready', function () {
console.log('deviceready OK!');
JSAPI.showToast(0, '提示信息')
}, false)
需要注意的是,在开发环境,是没有 deviceready
事件的,所以上面的代码并不会执行,只有在app
里面运行的时候才会执行。
思考:
JSBridge
必须是在deviceready
事件触发后方能使用的,因此首先要做的就是自定义deviceready
事件,本地环境可以在load
事件里触发自定义deviceready
事件,生产环境下监听deviceready
事件即可
4、JS发起自定义事件
我是用 CustomEvent
构造函数,继承至 Event
,文档看这里
- 用法
new CustomEvent(eventName, params);
- 示例
创建一个自定义事件
const event=new CustomEvent('mock-event');
- 传递参数
这里值得注意,需要把想要传递的参数包裹在一个包含detail
属性的对象,否则传递的参数不会被挂载
function createEvent(params, eventName = 'mock-event') {
return new CustomEvent(eventName, { detail: params });
}
const event = createEvent({ id: '0010' });
- 发起事件
调用dispatchEvent
方法发起事件,传入你刚才创建的方法
window.dispatchEvent(event);
- 监听事件
window.addEventListener('mock-event', ({ detail: { id } }) => {
console.log('id',id) // 会在控制台打印0010
});
- 示例:
document.body.addEventListener('show', (event) => { console.log(event.detail); });
// 触发
let myEvent = new CustomEvent('show', {
detail: {
username: 'xixi',
userid: '2022'
}
});
document.body.dispatchEvent(myEvent);
了解了自定义事件之后,通过自定义事件模拟触发
deviceready
事件,这样上面的deviceready
事件监听就可以执行了。注意:这里还要确定一个问题,在什么时候触发自定义事件
deviceready
呢?
5、确定 deviceready
事件执行时机
- 只需要编写如下代码,查看输出结果即可
window.addEventListener('load', function () {
console.log('load OK!');
}, false);
document.addEventListener('deviceready', function () {
console.log('deviceready OK!');
}, false);
- 结果输出
load OK!
deviceready OK!
由此可知,执行顺序:load
--> deviceready
6、自定义事件模拟Cordova
deviceready
事件
自定义
deviceready
事件根据上面测试执行顺序得出的结论,我在
load
事件里触发自定义事件在开发环境下模拟一些用到的
JSBridge-API
,比如下面写到的JSAPI.showToast()
方法
- mockEvent.js
if (process.env.NODE_ENV === 'development') {
// 自定义事件
let myEvent = new CustomEvent('deviceready');
// 模拟JSAPI事件
window['JSAPI'] = {
showToast(type, desc) {
console.log(type, desc);
}
}
// ...
// 开发环境下,在 原生 load 方法之后 触发自定义事件
window.addEventListener('load', function () {
console.log('load OK!');
setTimeout(() => {
document.body.dispatchEvent(myEvent);
}, 100)
}, false);
}
7、封装deviceReady
方法
实现在Cordova
框架触发deviceready
事件的时候感知到,以便于在deviceReady
事件触发后执行JS-API
。
可用于开发环境和非开发环境
7.1、方式一
这里采用链式调用的方式,
以下这种借助 Promise
的实现,在这种场景下其实是不合理的
只是形式上类似,其实并不是
- 定义
- mixin.js
deviceReady() {
return new Promise((resolve) => {
window.addEventListener('deviceready', function () {
resolve("ready go!");
}, false);
})
}
- 组件内使用
JS-API
使用JSAPI
可以如下这么写
this.deviceReady().then((res) => {
console.log(res); // ready go!
JSAPI.showToast(0, '提示')
})
this.deviceReady().then((res) => {
JSAPI.getUserInfo((res) => {
console.log(res);
}, (err) => {
console.log(err);
});
})
- 开发环境执行效果如下
7.2、方式二(推荐)
改写成通用的事件监听函数,支持链式调用
开发环境下,由
mockEvent.js
文件里的dispatchEvent
触发自定义的deviceready
事件;小程序里运行,则由真实的
deviceready
事件触发
- 定义
- mixin.js
receiver(type) {
let callbacks = {
fns: [],
then: function(cb){
this.fns.push(cb);
return this;
}
};
document.addEventListener(type, function(ev) {
let fns = callbacks.fns.slice();
for(let i = 0, l = fns.length; i < l; i++){
fns[i].call(this, ev);
}
});
return callbacks;
}
- 使用
this.receiver('deviceready').then((ev) => {
console.log(ev);
JSAPI.getUserInfo(
(res) => {
console.log(res);
},
(err) => {
console.log(err);
}
)
})
this.receiver("click")
.then(() => console.log("hi"))
.then(()=> console.log(22));
最后
当应用发布到app
上,就是监听的真实的 Cordova
框架的 deviceready
事件了,之后也就可以拿到真实的JSAPI
了,以上只是为了在开发环境的时候模拟使用JSAPI
。防止在开发环境下直接调用JSAPI
飘红的情况,当然也是可以加try catch
处理的,只不过个人感觉模拟事件使得代码看起来更加优雅别致一点,使用更加丝滑,酌情食用。
软件架构非常有意思,感兴趣的可以交流探索,嘻嘻。
我是 甜点cc
热爱前端,也喜欢专研各种跟本职工作关系不大的技术,技术、产品兴趣广泛且浓厚,等待着一个创业机会。主要致力于分享实用技术干货,希望可以给一小部分人一些微小帮助。
我排斥“新人迷茫,老人看戏”的现象,希望能和大家一起努力破局。营造一个良好的技术氛围,为了个人、为了我国的数字化转型、互联网物联网技术、数字经济发展做一点点贡献。数风流人物还看中国、看今朝、看你我。
Hybrid app本地开发如何调用JSBridge的更多相关文章
- Hybrid APP混合开发的一些经验和总结
http://www.cnblogs.com/kingplus/p/5588339.html 写在前面: 由于业务需要,接触到一个Hybrid APP混合开发的项目.当时是第一次接触混合开发,有一些经 ...
- Hybrid APP混合开发
写在前面: 由于业务需要,接触到一个Hybrid APP混合开发的项目.当时是第一次接触混合开发,有一些经验和总结,欢迎各位一起交流学习~ 1.混合开发概述 Hybrid App主要以JS+Nativ ...
- Hybrid App 应用开发中 9 个必备知识点复习(WebView / 调试 等)
前言 我们大前端团队内部 ?每周一练 的知识复习计划继续加油,本篇文章是 <Hybrid APP 混合应用专题> 主题的第二期和第三期的合集. 这一期共整理了 10 个问题,和相应的参考答 ...
- Hybrid App混合模式开发的了解
Hybrid App(混合模式移动应用)是指介于web-app.native-app这两者之间的app,兼具"Native App良好用户交互体验的优势"和"Web Ap ...
- (一)Hybrid app混合开发模式
hybrid app是什么? 这里我们先看一下词条上的定义 Hybrid App:Hybrid App is a mobile application that is coded in both br ...
- SharePoint 2013 搭建app本地开发环境
使用SharePoint App,如果要通过应用程序目录分发 SharePoint 相关应用程序,如具有完全控制权限的 SharePoint 相关应用程序(无法部署到 Office 365 网站),则 ...
- 【Hybrid App】Hybrid App开发实战
[引言]近年来随着移动设备类型的变多,操作系统的变多,用户需求的增加,对于每个项目启动前,大家都会考虑到的成本,团队成员, 技术成熟度,时间,项目需求等一堆的因素.因此,开发App的方案已经变得越来越 ...
- 跨平台 webapp 开发技术之 Hybrid App
前所知的 APP 开发模式有三种: 基于操作系统运行的 APP -> Native App,侧重于原生开发,用户体验好,需要安装才会升级 基于浏览器运行的 APP -> Web App,侧 ...
- Hybrid App开发实战
Hybrid App开发实战 作者 李秉骏 发布于 九月 04, 2013 | [引言]近年来随着移动设备类型的变多,操作系统的变多,用户需求的增加,对于每个项目启动前,大家都会考虑到的成本,团队成员 ...
随机推荐
- 7 个有趣的 Python 实战项目,超级适合练手
关于Python,有一句名言:不要重复造轮子. 但是问题有三个: 1.你不知道已经有哪些轮子已经造好了,哪个适合你用.有名有姓的的著名轮子就400多个,更别说没名没姓自己在制造中的轮子. 2.确实没重 ...
- MYSQL索引的建立、删除以及简单使用
一.前期数据准备 1.建表 CREATE TABLE `user` ( `uid` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAUL ...
- JavaWEB-01-MySQL基础
JavaWeb内容 数据库 – 数据存储 MySQL JDBC Maven - 项目管理工具 Mybatis 前端 - 为了前端哥们沟通 HTML+CSS JavaScript Ajax + Vue ...
- 'cross-env' 不是内部或外部命令
yarn start yarn run v1.22.10$ cross-env APP_TYPE=site umi dev'cross-env' 不是内部或外部命令,也不是可运行的程序或批处理文件.e ...
- Solution -「2021.11.27」\Infty
T1. 显然往 \(x < 0, y < 0\) 的点走一定不优. 根据转移式可发现 \(C(x, y)\) 即从 \((0, 0)\) 走到 \((x, y)\) 的方案数 \(\dbi ...
- 常用的函数式接口_Predicate接口_默认方法and和Predicate接口练习_集合接口筛选
默认方法:and 既然是条件判断,就会存在与.或.非三种常见的逻辑关系.其中将两个Preadicate条件使用"与"逻辑连接起来实现"并且"的效果时,可以使用d ...
- 第十七天python3 文件IO(三)
CSV文件 csv是一个被行分隔符.列分隔符化分成行和列的文本文件: csv不指定字符编码: 行分隔符为\r\n,最后一行可以没有换行符: 列分隔符常为逗号或者制表符: 每一行称为一条记录record ...
- 从零开始实现lmax-Disruptor队列(六)Disruptor 解决伪共享、消费者优雅停止实现原理解析
MyDisruptor V6版本介绍 在v5版本的MyDisruptor实现DSL风格的API后.按照计划,v6版本的MyDisruptor作为最后一个版本,需要对MyDisruptor进行最终的一些 ...
- 题解 洛谷 P2388 阶乘之乘
目录 简要题意 题解 主要思路 一个 \(\omega(n)\) 的算法 一个 \(O(\log n)\) 的算法 一个算法 代码 算法 \(1\)(\(\omega(n)\)) 算法 \(2\) 算 ...
- SAM复杂度证明
关于$SAM$的复杂度证明(大部分是对博客的我自己的理解和看法) 这部分是我的回忆,可省略 先回忆一下$SAM$ 我所理解的$SAM$,首先扒一张图 初始串$aabbabd$ 首先发现,下图里的$S- ...