小程序页面通信、数据刷新、event bus 解决方案之 iny-bus 2.0 来了
发布于 5 年前 作者 huxiulan 4390 次浏览 来自 分享

背景介绍

在很久之前,我在写小程序的时候需要遇到一些问题,为了解决这些问题,便有了 iny-bus 这个库,当时主要解决了那些问题呢,让我们回顾一下并介绍一下 2.0的新功能

存在问题

在各种小程序中,我们经常会遇到这种情况

有一个 列表,点击列表中的一项进入详情,详情有个按钮,删除了这一项,这个时候当用户返回到列表页时,

发现列表中的这一项依然存在,这种情况,就是一个 bug,也就是数据不同步问题,这个时候测试小姐姐

肯定会找你,让你解决,这个时候,你也许会很快速的解决,但过一会儿,测试小姐姐又来找你说,我打开了

四五个页面更改了用户状态,但我一层一层返回到首页,发现有好几个页面数据没有刷新,也是一个 bug

这个时候你就犯愁了,怎么解决,常规方法有下面几种

解决方法

将所有请求放到 生命周期 `` onShow `` 中,只要我们页面重新显示,就会重新请求,数据也会刷新
通过用 `` getCurrentPages `` 获取页面栈,然后找到对应的 页面实例,调用实例方法,去刷新数据
通过设置一个全局变量,例如 `` App.globalData.xxx ``,通过改变这个变量的值,然后在对应 `` onShow ``



中检查,如果值已改变,刷新数据
在打开详情页时,使用 `` redirectTo `` 而不是 `` navigateTo ``,这样在打开新的页面时,会销毁当前页面,



返回时就不会回到这个里面,自然也不会有数据不同步问题

存在的问题

假如我们将 所有 请求放到 `` onShow `` 生命周期中,自然能解决所有数据刷新问题,但是 `` onShow `` 这个生命周期,有两个问题



第一: 它其实是在 `` onLoad `` 后面执行的,也就是说,假如请求耗时相同,从它发起请求到页面渲染,



会比 `` onLoad `` 慢



第二:那就是页面隐藏、调用微信分享、锁频等等都会触发执行,请求放置于 `` onShow `` 中就会造成大量不需要的请求,造成服务器压力,多余的资源浪费、也会造成用户体验不好的问题
通过 `` getCurrentPages `` 获取页面栈,然后找到对应的页面实例,调用实例方法,去刷新数据,这也不失为一个办法,但是还是有限制



第一: `` getCurrentPages `` 无法获取 `` tabBar `` 页面,而`` tabBar `` 页面是需要刷新和通信的重灾区



第二: 当需要通信的页面有两个、三个、多个呢,这里去使用 `` getCurrentPages `` 就会比较困难、繁琐
通过设置全局变量的方法,当需要使用的地方比较少时,可以接受,当使用的地方多的时候,维护起来就会很困难,代码过于臃肿,也会有很多问题
使用 redirectTo 而不是navigateTo,从用来体验来说,很糟糕,并且只存在一个页面,对于tab 页面,它也无能为力,不推荐使用

最佳实践

在 Vue 中, 可以通过 new Vue() 来实现一个 event bus作为事件总线,来达到事件通知的功能,在各大

框架中,也有自身的事件机制实现,那么我们完全可以通过同样的方法,实现一个事件中心,来管理我们的事件,

同时,解决我们的问题。iny-bus 就是这样一个及其轻量的事件库,使用 typescript 编写,100% 测试覆

盖率,能运行 js 的环境,就能使用

安装

方式一. 通过 npm 安装

小程序已经支持使用 npm 安装第三方包,详见 npm 支持


# npm

npm i iny-bus -save

# yarn

yarn add iny-bus --production

方式二. 下载代码

直接通过 git 下载 iny-bus 源代码,并将dist目录 中的 index.js 拷贝到自己的项目中


git clone https://github.com/landluck/iny-bus.git

使用

使用内置方法(2.0 推荐)



  // App、Page、Component 使用方法一致,完全不需要手动去添加监听和移除监听了

  import bus from 'iny-bus'

  // bus.app bus.page bus.component

  const page = bus.page({

    busEvents: {

      // 简单使用

      postMessage(msg) {

        this.setData({

          msg

        })

      },

      // 一次性事件

      postMessageOnce: {

        handler (msg) {

          this.setData({

            msg

          })

        },

        once: true

      }

    },

    onLoad() {

      bus.emit('postMessage', 'hello bus')

      bus.emit('postMessageOnce', 'hello bus once')

    }

  })

  Page(page)

在生命周期中使用(1.0使用 和 2.0完全兼容)



  // 小程序

  import bus from 'iny-bus'

  // 添加事件监听

  // 在 onLoad 中注册, 避免在 onShow 中使用

  onLoad () {

    this.eventId = bus.on('事件名', (a, b, c, d) => {

      // 支持多参数

      console.log(a, b, c, d)

      this.setData({

        a,

        b,

        c

      }

    })

  }

  // 移除事件监听,该函数有两个参数,第二个事件id不传,会移除整个事件监听,传入ID,会移除该页面的事件监听,避免多余资源浪费, 在添加事件监听后,页面卸载(onUnload)时建议移除

  onUnload () {

    bus.remove('事件名', this.eventId)

  }

 

  // 派发事件,触发事件监听处更新视图

  // 支持多参传递

  onClick () {

    bus.emit('事件名', a, b, c)

  }

  

  // 清空所有事件监听

  onClear () {

    bus.clear()

  }

 

借助 iny-bus 小程序webview和原生通信

小程序 webview 和原生页面怎么通信,我相信这是一部分同学遇到的一个很不好处理的问题,那么如何借助 iny-bus 来实现 小程序 webview 和原生页面通信呢

  1. webview 和原生通信要借助 web-view 组件的 bindmessage 方法

  1. 要提前在小程序中内置好 iny-bus 的事件监听
  2. 要在 H5 中使用 wx.miniProgram.postMessage

  1. 参考以下代码
  // 小程序 webview
  // web-view 组件的 bindmessage 方法
  onMessage ({ detail: { data } }) {
    for (let i = 0; i < data.length; i++) {
        const event = data[i]
        // 分享事件
        if (event.type === 'share') {
        }
        // 刷新事件
        if (event.type === 'refresh' && event.name) {
          // 派发事件,传递参数
          bus.emit(event.name, event.data)
        }
        // 其它事件
     }
  }
  // H5
  wx.miniProgram.postMessage(
    { 
        type: 'refresh',
        name: 'refreshData',
        data: {
            a: 1
        }
    }
  )

最后

iny-bus 的核心代码,非常少,但是能解决我们在小程序中遇到的大量 通信 和 数据刷新问题,是采用 各大平台小程序 原生开发时,页面通信的不二之选,同时,100% 的测试覆盖率,确保了 iny-bus 在使用中的稳定性和安全性,当然,每个库都是从简单走向复杂,功能慢慢完善,如果

大家在使用或者源码中发现了bug或者可以优化的点,欢迎大家提 pr 或者直接联系我

最后,如果 iny-bus 给你提供了帮助或者让你有任何收获,请给 作者 点个赞,感谢大家 点赞 代码地址

回到顶部