Cordova框架做的webview
当调用JSAPI时,必须在页面完全加载完成之后才能够拿到全局的JSAPI,Cordova框架提供deviceready事件,该事件触发的时候表示全局的JSAPI挂载成功。
简单写下如下:

  1. document.addEventListener('deviceready', function () {
  2. console.log('deviceready OK!');
  3. JSAPI.showToast(0, '提示信息')
  4. }, false)

需要注意的是,在开发环境,是没有 deviceready 事件的,所以上面的代码并不会执行,只有在app里面运行的时候才会执行。于是,就可以用到上一篇写的: 自定义事件CustomEvent, 通过自定义事件模拟触发deviceready事件,这样上面 deviceready 事件监听就可以执行了。
这里还要确定一个问题,在什么时候触发自定义事件deviceready。
执行顺序:load -> deviceready

  1. window.addEventListener('load', function () {
  2. console.log('load OK!');
  3. }, false);
  4. document.addEventListener('deviceready', function () {
  5. console.log('deviceready OK!');
  6. }, false);
  7. // 输出: load OK! -> deviceready OK!

自定义事件模拟Cordova deviceready事件

并模拟一些用到的JS-API,比如下面写到的 JSAPI.showToast() 方法

  1. if (process.env.NODE_ENV === 'development') {
  2. // 触发
  3. let myEvent = new CustomEvent('deviceready');
  4. // 模拟JSAPI事件
  5. window['JSAPI'] = {
  6. showToast(type, desc) {
  7. console.log(type, desc)
  8. }
  9. }
  10. // ...
  11. // 在 原生 load 方法之后 触发自定义事件
  12. window.addEventListener('load', function () {
  13. console.log('load OK!');
  14. setTimeout(() => {
  15. document.body.dispatchEvent(myEvent);
  16. }, 100)
  17. }, false);
  18. }

封装deviceReady方法

实现在Cordova框架触发deviceready事件的时候感知到,以便于在deviceReady方法返回后执行JS-API。
可用于开发环境和非开发环境。

方式一

这里采用链式调用的方式,
以下这种借助 Promise 的实现,在这种场景下其实是不合理的

定义

  1. deviceReady() {
  2. return new Promise((resolve) => {
  3. window.addEventListener('deviceready', function () {
  4. resolve("ready go!")
  5. }, false);
  6. })
  7. }

组件内使用JS-API

使用JSAPI可以如下这么写

  1. this.deviceReady().then((res) => {
  2. console.log(res) // ready go!
  3. JSAPI.showToast(0, '提示')
  4. })
  5. this.deviceReady().then((res) => {
  6. // JSAPI.getUserInfo((res) => {
  7. // console.log(res)
  8. //}, (err) => {
  9. // console.log(err)
  10. //})
  11. })

开发环境执行效果如下:

image.png
改写成通用的事件监听函数,支持链式调用

方式二

定义

  1. receiver(type) {
  2. let callbacks = {
  3. fns: [],
  4. then: function(cb){
  5. this.fns.push(cb)
  6. return this
  7. }
  8. }
  9. document.addEventListener(type, function(ev) {
  10. let fns = callbacks.fns.slice()
  11. for(let i = 0, l = fns.length; i < l; i++){
  12. fns[i].call(this, ev)
  13. }
  14. });
  15. return callbacks
  16. }

使用

  1. this.receiver('deviceready').then((ev) => { console.log(ev); })
  2. this.receiver("click").then(() => console.log("hi")).then(()=>console.log(22));

最后

当应用发布到app上,就是监听的真实的 Cordova框架的 deviceready 事件了,之后也就可以拿到真实的JSAPI了,以上只是为了在开发环境的时候模拟使用JSAPI。防止在开发环境下直接调用JSAPI飘红的情况,当然也是可以加try catch处理的,只不过个人感觉模拟事件使得代码看起来更加优雅别致一点,酌情食用。