Skip to content

lijsh/omina

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

24 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Omina

一个简约的小程序增强库,提供了全局状态同步及增强的小程序原生对象(Page 实例及 App 实例)。

特点

  • 轻量:聚焦 framework free 的原生开发,大小不到 10Kb,只包含必要的逻辑及两个蝇量级依赖 :)
  • 全局状态响应式同步:fork 了 Vue 中 observe 的逻辑,实现了页面 dataglobalData 的同步
  • 集成事件总线
  • 增强的 Page 实例及 App 实例
  • wx 接口的 promisify

使用方法

import { page } from 'libs/omina'

page({
  onLoad(options) {}
})
  • omina 也支持通过 npm install omina 安装为项目依赖,最后通过开发工具自带 npm 构建功能或打包工具(Webpack、Rollup 等)的构建功能将 omina 打包到 build 中。
import { app } from 'omina'

app({
  onLaunch() {}
})

API

omina 暂时只暴露 pageapp 两个 API,PageApp 的增强、globalData 的 observe、wx 接口的 promisify 均由 omina 在内部实现。

页面实例属性及方法

  • mapData

mapData 属性作为配置选项传进 page 函数,是页面 dataglobalData 保持同步的关键。mapData 对象中 key 的值均为函数,最终会定义为 page 中 data 上对应的 key,当 key 函数中依赖的 globalData 字段发生变动,omina 会自动调用 setData 更新对应的 data

import { page } from 'omina'

page({
  mapData: {
    // this.data.userInfo 会与 app.globalData.userInfo 保持同步
    userInfo(app) {
      return app.globalData.userInfo // 假设 app.globalData.userInfo 初始值为 null
    }
  }
  onLoad() {
    console.log(this.data.userInfo) // null
    app.globalData.userInfo = { nickName: 'Omina' } // next tick 后 this.data.userInfo 变成 { nickName: 'Omina' }
  }
})

mapData 建立的数据同步是跨页面的,只要页面还保留在页面栈中没卸载,修改 globalData 会触发页面对应 data 的修改。

不过直接修改 globalData 不利于代码复用与封装,ominaApp 实例中暴露了一个事件总线,你可以充分利用自定义事件机制来达成类似 Vuex 的效果:

import { app } from 'omina'
app({
  onLaunch() {
    app.bus.on('foo', (data) => {
      app.set(app.globalData, 'foo', data)
    })
  }
})

// 在某页面调用
app.bus.emit('foo', { testFoo: 'testFoo' })
  • $prevPage

获取上一页的页面对象,在一些只涉及到两个页面的跨页面通讯中用起来更方便。

// Page A
page({
  data: {
    foo: 'bar'
  },
  methodsA() {
    console.log('这是 A 页面的方法')
  }
})

// Page B;假设由 A 跳转到 B
page({
  data: {},
  onLoad() {
    console.log(this.$prevPage.data) // 打印出 Page A 的 data 属性,即 { foo: 'bar' }
    this.$prevPage.methodsA() // 打印出 '这是 A 页面的方法'
  }
})
  • $navTo({ url, params })

跳转到 url 指定页面,同时传递 params 参数,此参数可在下一页的 onLoad 中取回:

// A 跳转 B
page({
  onLoad() {
    this.$navTo({ url: 'urlToB', params: { foo: 'bar' } })
  }
})

// B 页面的 onLoad
page({
  onLoad(options) {
    console.log(options.params) // { foo: 'bar' }
  }
})
  • $on / $emit

所有页面对象(通过 ominapage 方法生成的页面对象)都集成了同一个事件总线,这个事件总线为页面对象增加了 $on$emit 方法,方便实现跨页面通信。这个事件总线与 App 实例上的 bus 不是同一个对象。

// Page A 中定义
this.$on('test', console.log)

// 跳转到 Page B
this.$emit('test', { foo: 'bar' }) // log 出 { foo: 'bar' }

omina 会在页面 unload 的时候自动清除当前页面监听的事件,如果不希望事件监听被自动清除,请使用 App 上的 bus

总结一下,在 omina 中实现跨页面数据传输的方法有三种:

  1. 通过 mapData 将页面数据与 globalData 绑定,修改 globalData 时所有对被修改属性有依赖的页面自动 setData
  2. 使用 $prevPage 属性获取上一页面的 data 及调用上一页面的方法
  3. 使用 $on$emit 通过自定义事件的监听与触发实现跨页面通讯

扩展原生 Page 实例的原理,可参考 扩展原生 Page 对象

全局对象实例属性及方法

App 实例上代理了 'wx' 对象上的 API,其中回调风格的 API 均进行了 promisify:

import { app } from 'omina'

app({
  onLaunch() {
    this.login()
      .then(res => {
        console.log(res.code)
      })
  }
})
  • bus

App 实例上的 bus 属性是 mitt 实现的全局单例事件总线,具体 API 请参考 mitt

  • set

类似 Vue.setOminaApp 实例增加了一个 set 方法,用来显式给 observe 后的对象添加新属性:

const app = getApp()
app.set(app.globalData, 'someKey', 'someVal')
  • del

类似 Vue.delete

TODO

  • Component 的增强
  • 支持 Computed 属性
  • request 方法的增强

具体实现可参考这篇文章:https://juejin.im/post/5b55c1056fb9a04f951d1d4b

About

🎡 小程序运行时增强库

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published