Cordova框架做的webview
当调用JSAPI时,必须在页面完全加载完成之后才能够拿到全局的JSAPI,Cordova框架提供deviceready事件,该事件触发的时候表示全局的JSAPI挂载成功。
简单写下如下:
document.addEventListener('deviceready', function () {console.log('deviceready OK!');JSAPI.showToast(0, '提示信息')}, false)
需要注意的是,在开发环境,是没有 deviceready 事件的,所以上面的代码并不会执行,只有在app里面运行的时候才会执行。于是,就可以用到上一篇写的: 自定义事件CustomEvent, 通过自定义事件模拟触发deviceready事件,这样上面 deviceready 事件监听就可以执行了。
这里还要确定一个问题,在什么时候触发自定义事件deviceready。
执行顺序:load -> deviceready
window.addEventListener('load', function () {console.log('load OK!');}, false);document.addEventListener('deviceready', function () {console.log('deviceready OK!');}, false);// 输出: load OK! -> deviceready OK!
自定义事件模拟Cordova deviceready事件
并模拟一些用到的JS-API,比如下面写到的 JSAPI.showToast() 方法
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);}
封装deviceReady方法
实现在Cordova框架触发deviceready事件的时候感知到,以便于在deviceReady方法返回后执行JS-API。
可用于开发环境和非开发环境。
方式一
这里采用链式调用的方式,
以下这种借助 Promise 的实现,在这种场景下其实是不合理的
定义
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)//})})
开发环境执行效果如下:

改写成通用的事件监听函数,支持链式调用
方式二
定义
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); })this.receiver("click").then(() => console.log("hi")).then(()=>console.log(22));
最后
当应用发布到app上,就是监听的真实的 Cordova框架的 deviceready 事件了,之后也就可以拿到真实的JSAPI了,以上只是为了在开发环境的时候模拟使用JSAPI。防止在开发环境下直接调用JSAPI飘红的情况,当然也是可以加try catch处理的,只不过个人感觉模拟事件使得代码看起来更加优雅别致一点,酌情食用。
