omi/packages/omix-v1
dntzhang d53a17cea5 fix: remove dead code 2019-10-17 22:31:49 +08:00
..
components chore: rename omix 2019-10-03 10:09:46 +08:00
pages chore: rename omix 2019-10-03 10:09:46 +08:00
utils fix: remove dead code 2019-10-17 22:31:49 +08:00
README.md chore: rename omix 2019-10-03 10:09:46 +08:00
app.js chore: rename omix 2019-10-03 10:09:46 +08:00
app.json chore: rename omix 2019-10-03 10:09:46 +08:00
app.wxss chore: rename omix 2019-10-03 10:09:46 +08:00
project.config.json chore: rename omix 2019-10-03 10:09:46 +08:00
sitemap.json chore: rename omix 2019-10-03 10:09:46 +08:00
store.js chore: rename omix 2019-10-03 10:09:46 +08:00

README.md

omix

极小却精巧的小程序框架,对小程序入侵性几乎为零

5分钟精通

API

去中心化 API

  • create.Page(option) 创建页面option.context 页面级别共享
  • create.Component(option) 创建组件
  • this.oData 操作页面或组件的数据(会自动更新视图)
  • this.context 页面注入的 context页面和页面所有组件可以拿到
  • create.mitt() 事件发送和监听器

中心化 API

  • create(store, option) 创建页面, store 可跨页面共享
  • create(option) 创建组件
  • this.store.data 全局 store 和 data页面和页面所有组件可以拿到 操作 data 会自动更新视图
  • create.emitter 事件发送和监听器,不同于 mitt() 每次会创建新的实例emitter 是全局唯一,可以用于跨页面通讯

实战去中心化 API

页面

import create from '../../utils/create'

const app = getApp()

create.Page({
  //页面级别上下文,跨页面不共享
  context: {
    abc: '公共数据从页面注入到页面的所有组件'
    //事件发送和监听器,或者 create.mitt()
    emitter: create.emitter
  },
  data: {
    motto: 'Hello World',
    userInfo: { },
    hasUserInfo: false,
    canIUse: wx.canIUse('button.open-type.getUserInfo')
  },
  ...
  ...
  onLoad: function () {

    ...
    ...
    ...
    //监听事件
    this.context.emitter.on('foo', e => console.log('foo', e) )
    setTimeout(() => {
      this.oData.userInfo = {
        nickName: 'dnt',
        avatarUrl: this.data.userInfo.avatarUrl
      }
    }, 2000)


    setTimeout(() => {
      this.oData.userInfo.nickName = 'dntzhang'
    }, 4000)
  }
})

这里需要注意oData 必须直接操作 data 里定义好的数据才能直接更新视图,比如 nickName 一开始没有定义好,更新它是不会更新视图,只有通过下面代码执行之后,才能更新 nickName因为 userInfo 的变更会自动监听 userInfo 内的所有属性:

this.oData.userInfo = {
  nickName: 'dnt',
  avatarUrl: this.data.userInfo.avatarUrl
}

当然你也可以直接在 data 里声明好:

  data: {
    motto: 'Hello World',
    userInfo: { nickName: null },
    ...

组件

import create from '../../utils/create'

create.Component({
  data: {
    a: { b: Math.random() }
  },

  ready: function () {
    //这里可以获取组件所属页面注入的 store
    console.log(this.context)
    //触发事件
    this.context.emitter.emit('foo', { a: 'b' })
    setTimeout(()=>{
      this.oData.a.b = 1
    },3000)
  },
})

数组

import create from '../../utils/create'
import util from '../../utils/util'

create.Page({
  data: {
    logs: []
  },
  onLoad: function () {
    this.oData.logs = (wx.getStorageSync('logs') || []).map(log => {
      return util.formatTime(new Date(log))
    })

    setTimeout(() => {
      this.oData.logs[0] = 'Changed!'
    }, 1000)

  }
})

这里需要注意,改变数组的 length 不会触发视图更新,需要使用 size 方法:

this.oData.yourArray.size(3)

其他

this.oData.arr.push(111) //会触发视图更新
//每个数组的方法都有对应的 pureXXX 方法
this.oData.arr.purePush(111) //不会触发视图更新

this.oData.arr.size(2) //会触发视图更新
this.oData.arr.length = 2 //不会触发视图更新

 函数属性

data: {
    motto: 'Hello World',
    reverseMotto() {
      return this.motto.split('').reverse().join('')
    }
},

其中 reverseMotto 可以直接绑定在 wxml 里motto 更新会自动更新 reverseMotto 的值。

mitt 语法

const emitter = mitt()

// listen to an event
emitter.on('foo', e => console.log('foo', e) )

// listen to all events
emitter.on('*', (type, e) => console.log(type, e) )

// fire an event
emitter.emit('foo', { a: 'b' })

// working with handler references:
function onFoo() {}
emitter.on('foo', onFoo)   // listen
emitter.off('foo', onFoo)  // unlisten

详细参见 mitt github

omix 为 mitt 新增的语法:

emitter.off('foo') // unlisten all foo callback

实战中心化 API

定义 store:

export default {
  data: {
    logs: []
  }
}

定义页面:

import create from '../../utils/create'
import util from '../../utils/util'
import store from '../../store'

create(store, {
  onLoad: function () {
    this.store.data.logs = (wx.getStorageSync('logs') || []).map(log => {
      return util.formatTime(new Date(log))
    })


    setTimeout(() => {
      this.store.data.logs[0] = 'Changed!'
    }, 1000)


    setTimeout(() => {
      this.store.data.logs.push(Math.random(), Math.random())
    }, 2000)

    setTimeout(() => {
      this.store.data.logs.splice(this.store.data.logs.length - 1, 1)
    }, 3000)
  }
})
<view class="container log-list">
  <block wx:for="{{store.logs}}" wx:for-item="log">
    <text class="log-item">{{index + 1}}. {{log}}</text>
  </block>
  <view>
    <test-store></test-store>
  </view>
</view>

可以看到里面使用 test-store 组件, 看下组件源码:

import create from '../../utils/create'

create({
  
})
<view class="ctn">
  <view>
    <text>Log Length: {{store.logs.length}}</text>
  </view>
</view>

喜欢中心化还是喜欢去中心化任你挑选,或者同一个小程序可以混合两种模式。

MIT Lic