redux-miniprogram-bindings
适用于小程序的 Redux 绑定辅助库
特性
- API 简单灵活,只需一个
connect
即可轻松使用(提供$page
和$component
别名快捷方法) - 功能完善,提供了多种使用方式,可满足不同的需求和使用场景
- 支持在 XML 中使用
- 执行 dispatch 后所有未销毁的页面(或组件)内部状态自动更新,视图自动队列批量更新渲染
- 自动进行 diff 优化和批量队列更新处理,性能优异
- 支持
微信小程序
和支付宝小程序
安装
-
通过
npm
或yarn
安装# npm$ npm install --save redux-miniprogram-bindings redux# yarn$ yarn add redux-miniprogram-bindings redux -
也可以直接引入
dist
目录下对应的redux-miniprogram-bindings
文件 -
需要单独引入 redux 文件(这只是个绑定库,并不包含 redux 的代码在内)
使用
-
创建 Redux 的 Store 实例
// store.js{}const initUserInfo = name: 'userName' age: 25{}const rootReducer =const store = -
在
app.js
文件中设置 provider// setupStore.js// 微信小程序// 支付宝小程序// import { setProvider } from 'redux-miniprogram-bindings/dist/redux-miniprogram-bindings.alipay.min.js'// app.js// 确保在其他代码之前调用 -
在页面中使用
{// 读取 state 中的值const dependent = thisdata// dispatch actionCreator1this// dispatch actionCreator2this} -
在组件中使用
{// 读取 state 中的值const data1: dependent = thisdata// dispatch actionCreator1this// dispatch actionCreator2this} -
在 XML 中使用
{{ data2 }}
API
(config) => void
setProvider:设置 Provider
-
config 对象的属性:
-
store:
Store
Redux 的 Store 实例对象,必传
-
namespace:
string
命名空间,默认为空
当设置命名空间后,会将所有依赖的 state 数据存放到
以命名空间字段值为 key
的对象中,此时读取 state 值需要加上命名空间字段值例如设置
namespace: '$store'
,那么在页面(或组件)中获取依赖的 state 值需要使用this.data.$store.xxx
形式,在 XML 中也需要加上前缀:<view>{{ $store.xxx }}</view>
命名空间存在的意义:
- 明确哪些数据是来自于 store
- store 中的数据必须通过 dispatch 才能触发更新。命名空间可以避免无意中使用
this.setData
造成 store 中的数据被修改,因为需要加上额外的命名空间前缀:this.setData({ '$store.xxx': xxx })
-
component2:
boolean
是否开启了 component2,默认为
false
,仅支付宝小程序
支持
-
-
该函数必须在所有用到
store
的代码之前调用最佳实践:
要保证
setProvider
在所有用到store
的代码之前调用,但是代码中各处充斥着对store
的使用,如何保证?可以单独新建一个 js 文件(例如
setupStore.js
)用来调用setProvider
,然后在app.js
文件最顶部引入该文件即可// setupStore.js// 微信小程序// app.js
(config) => (options) => void | options
connect:连接 store
-
config 对象的属性:
-
type:
"page" | "component"
所连接实例的类型,默认为
page
,可选值:page
、component
-
mapState:
(string | ((state: Object) => Object))[]
实例依赖的 state,可选
会将依赖的 state 数据注入到 data 中,并在后续状态改变时自动更新。是个数组类型,数组中可以包含字符串、函数
-
数组中的字符串:字符串为依赖的 state 的相应的 key 值,页面(或组件)会在依赖的 state 发生改变时自动更新状态和队列批量触发视图渲染
// state1、state2 为 store 的 state 中的 key 值// store.getState().state1// store.getState().state2mapState: 'state1' 'state2' -
数组中的函数:函数接收 state 作为参数,可通过 state 获取到最新的状态数据,该函数必须返回一个对象,对象中的每一项可以是任意值,一般是根据 state 组合的数据
该方式会在 store 数据发生改变(并非一定是当前实例依赖的状态发生改变)时执行函数,然后对函数返回的结果和现有 data 中的数据进行 diff 比较,确认发生改变后队列批量更新渲染
mapState:region: stateprovince + statecity + stateareaname: stateuserInfoname -
字符串和函数混合:函数会在每次 store 数据发生改变时调用,请确保函数足够的小和快。出于性能优化,建议多使用字符串形式,减少使用函数形式,必要时将两种形式混合使用
mapState:'name'region: stateprovince + statecity + statearea
-
-
mapDispatch:
Object | dispatch => Object
注入可执行的 dispatch 处理函数,可选
-
对象形式:
key
值为自定义函数名,实例内部可以通过该名称访问该方法,value
值为actionCreator
函数。会将 actionCreator 函数包装成自动调用 disptach 的函数,并注入到实例方法中// 配置mapDispatch:methodsName1: actionCreator1methodsName2: actionCreator2// 调用this// 相当于// 调用this// 相当于 -
函数形式:函数接收 dispatch 作为参数,返回一个对象,包含自定义整理后的处理函数
// 配置// 调用thisthis
注意: 通过 mapDispatch 注入的函数也可以在 XML 中作为事件处理函数使用。如果函数需要传递参数时请注意,事件处理函数默认会传入
event
对象作为函数的第一个参数Add -
-
manual:
boolean
是否需要手动调用
Page()
或Component()
,默认值为false
当设置为
true
时,connect
会返回处理好的传入的 options 对象,需要手动调用Page()
或Component()
进行实例注册。这为使用者自定义扩展提供了途径const options =// ...optionsxxx = 'xxx'
-
-
扩展封装:可能你不喜欢
connect
的传参方式,或者不想使用前还要引用,那么可以自行扩展封装示例扩展 Page:
// bootstrap.jsconst oldPage = Page{const mapState mapDispatch ...restOptions = optionsconst realOptions =restOptions}// app.js// 引入扩展// 使用
$page
connect Page 的别名
{}// 相当于{}
$component
connect Component 的别名
{}// 相当于{}
Utils
() => Store
useStore: 获取 store 实例对象
const store = // 相当于如下方式,但是支付宝小程序分包时不建议使用如下方式,会出现多 store 实例
() => Object
useState: 获取当前 state 对象
const state = // 相当于如下方式,但是支付宝小程序分包时不建议使用如下方式,会出现多 store 实例const state = store
() => Dispatch
useDispatch: 获取 dispatch 函数
const dispatch = // 相当于如下方式,但是支付宝小程序分包时不建议使用如下方式,会出现多 store 实例const dispatch = storedispatch
useSubscribe
添加 store 订阅
接收一个回调函数,该函数会在 store 数据发生改变时调用,该函数接收两个参数,分别是当前状态 currState 和之前状态 prevState,通过对比两者数据实现细化监听
返回一个函数,调用该函数可以取消订阅
{ // 启用订阅 thisunsubscribe = } { // 解除订阅 this }
useRef
获取 state 对象中数据的引用
接收一个 selector 函数,该函数接收 state 作为参数,可以返回任意值(建议返回使用 state 组装的数据)
返回一个 Ref 对象,该对象拥有一个只读的 value 属性,通过该属性可以得到 selector 函数返回的最新值
const selector = stateuserInfonameconst userNameRef =
也可以通过如下方式实现相同功能
const selector = stateuserInfonameconst getUserName =
具体使用哪种方式完全看个人喜好,这里只是提供了一个工具方法
useSelector
对 selector 函数结果进行缓存
接收一个 selector 函数,该函数接收 state 作为参数,可以返回任意值(建议返回使用 state 组装的数据)
同时接受一个 deps 数组,该数组包含 selector 函数结果变更依赖的 state 的 key 值
返回一个同 selector 函数签名一致的函数,该函数每次执行时会对依赖项 deps 数组中每一项的值进行浅比较,只有依赖项的值发生改变时才会重新执行函数,降低复杂逻辑函数的执行频率
// 配合 useRef 使用// 只在 state.userInfo 发生改变时才会重新执行const userNameselector = const userNameRef =
// 配合 mapState 使用// 只在 state.userInfo 发生改变时才会重新执行const userNameSelector = {}