1.0.0 • Published 4 years ago

mpext v1.0.0

Weekly downloads
1
License
MIT
Repository
github
Last release
4 years ago

mpext

对原生小程序开发进行简单的扩展封装

特性

  • 可直接使用Redux作为全局状态管理,触发更新后,未销毁的页面(组件)内状态自动更新
  • setData的数据进行diff优化
  • 支持mixin混入

使用Redux

  • 创建store

mpext本身并不包含Redux,需单独引用

import { combineReducers, createStore } from 'redux'
import counter from 'reducers/counter'

const rootReducer = combineReducers({
  counter,
})

const store = createStore(rootReducer)

export default store
  • app.js中将store连接到mpext
import { setStore } from 'mpext'
import store from 'store'

setStore(store)

App({
  // ...
})
  • 使用store

注册页面或组件时需要使用mpext提供的$page$component

import { $page, $component } from 'mpext'
import { setCounter } from 'actions/counter'

$page({
  storeName: '$store',
  mapState: ['counter'],
  mapDispatch: { setCounter },
})({
  // ...
})

为了标识该状态为全局状态,会将页面(组件)引用的全局状态统一注入到一个对象中,该对象在data中的属性名为storeName的值,默认为$store

<view>{{ $store.counter }}</view>

mapState属性必须传入一个字符串数组,各个字符串为该页面(组件)需要引入的全局状态的key值。data中只会挂载在mapState中声明的全局状态,同时也只有在mapState中声明的全局状态在状态更新时自动触发页面(组件)更新

// 获取 store 方式一
import { getStore } from 'mpext'
const store = getStore()
// 获取 store 方式二
import store from 'store'

// 获取所有的全局状态
const state = store.getState()

mapDispatch属性必须为一个Objectkey值为在页面(组件)内可访问的方法名,值为actionCreator函数,通过该方法,可以自动将dispatch绑定到actionCreator函数上,并挂载到页面(组件)上,方便调用。全局状态只能通过dispatch触发action进行更新,不能通过setData更新

$page({
  mapDispatch: { increment },
})({
  // 通过 mapDispatch 注入的可直接调用,触发状态更新
  handleIncrement() {
    this.increment(1)
  },
})

import { getStore } from 'mpext'
import { setCounter } from 'store/actions/counter'

const store = getStore()

$page()({
  handleDecrement() {
    // 没有通过 mapDispatch 注入的,可以通过 store.dispatch 触发更新
    store.dispatch(setCounter(0))
  },
})

注意:如果直接将通过mapDispatch注入的方法绑定到事件处理上,请确保该方法不需要传入参数,因为事件处理函数默认会传入event对象作为第一个参数

<!-- handleAdd 的第一个参数会接收 event 对象 -->
<view bind:tap="handleAdd">Add</view>

diff优化

使用Redux管理的全局状态会在更新时自动进行diff处理,将setData的数据量降到最低

对于普通数据更新提供了$setData方法,并没有直接覆盖setData方法,因为diff优化本身是耗时的。最好的优化方式是使用setData,将key以数据路径的形式给出,改变数组中的某一项或对象中的某个属性。对于一些明确知道数据类型为基本类型的,也建议使用setData的方式更新数据,因为对基本类型的数据进行diff是无意义的。只有对于一些不知道哪里会更改或主动优化比较麻烦的引用类型值,才建议使用$setData方法。同时$setData也支持将key以数据路径的形式给出,但是不会对其值进行diff操作,因为对于数据路径形式的keympext会认为你已经做好了diff优化,不需要再次diff

$page()({
  data: {
    a: { b: [1, { c: 1 }, 3] },
    b: { b: [1, { c: 1 }, 3] },
  },

  onLoad() {
    this.$setData({
      a: { b: [1, { c: 2 }, 3, 4] },
      'b.b[0]': 2,
    })
  },
})

diff逻辑 'diff'

mixin混入

目前只支持方法的全局混入,即需要在app.js中定义混入,在各个页面或组件中都可以使用。

因为小程序的Component构造器自带有behaviors属性,类似于mixins,实现组件间代码共享,同时小程序的页面也可以视为组件,可以使用Component构造器进行构造。使用Component构造的页面不仅可以使用Page的属性和方法,也能使用Component的属性和方法,可以使页面功能更加强大。在此,也极力推荐大家使用Component构造页面。所以,后续会在$page中统一使用Component构造页面,实现完善的mixin

import { setMixin } from 'mpext'

setMixin({
  showData() {
    console.log('当前页面(组件)的data:', this.data)
  },
})