本文主要讲述, 在微信小程序中如何使用 redux
DEMO https://GitHub.com/tornoda/miniProgram-with-redux
需要解决的问题
如何在小程序中引入 redux 状态管理库, 及它相关的插件?
微信小程序没有清晰的异步 API, 便于 thunkMiddleware 处理异步请求 (异步操作), 如何解决?
如何正确使用 store 的三大核心方法 (getStore dispatch subscribe)?
redux 并不是 react 专属, 所以他可以在任何地方使用, 小程序也不例外. 解决上面三个问题就可以了.
问题一: 如何在小程序中引入 redux 状态管理库, 及它相关的插件?
使用 NPM 在临时目录里安装 redux 和其他你需要用到的包, 如: logger thunkMiddleware. 这里以 redux 示例.
进入 node_module 中, 拷贝如下文件:
\redux\dist\redux.JS
或者
\redux\dist\redux.min.JS
根据 1/2 中的步骤. 把 redux.JS logger.JS thunkMiddleware 都拷贝到小程序项目文件夹 \ module 目录下, 没有请新建.
问题二: 微信小程序没有清晰的异步 API, 便于 thunkMiddleware 处理异步请求 (异步操作), 如何解决?
前面有文章已经写过, 如何将微信异步 API 转换为 Promise, 便于异步编程: 把微信小程序异步 API 转为 Promise, 简化异步编程
读完会, 把 to-promise 库和 redux 一样放在 \ module 文件夹下
问题三: 如何正确使用 store 的三大方法 (getStore dispatch subscribe)?
这也是最关键的
在 App.JS 中创建 store
- //App.JS
- import reducer from './reducer/index'
- import { createStore, applyMiddleware } from './module/redux'
- import logger from './module/redux-logger'
- import thunkMiddleware from './module/redux-thunk'
- // 创建 redux store
- export const store = createStore(
- reducer,
- applyMiddleware(
- logger,// 用于控制台 state 调试
- thunkMiddleware// 用于处理异步 action
- )
- )
- App({
- //...
- })
编写 action
- // 项目根目录 / action/http3Steps.JS
- export const REQUSET_BEGIN = 'REQUEST_BEGIN'
- export const RECEIVED = 'RECEIVED'
- export const REQUEST_FAILED = 'REQUEST_FAILED'
- // 创建三个请求 http 事务时的状态 action, 用于处理通用 http 请求
- //1 请求开始; 2 收到请求; 3 请求失败
- export const requestBegin = (requestName) => ({
- type: REQUSET_BEGIN + requestName
- })
- export const received = (requestName, res) => ({
- type: RECEIVED + requestName,
- res
- })
- export const requestFailed = (requestName, err) => ({
- type: REQUEST_FAILED + requestName,
- err
- })
编写索引 action:
- // 项目根目录 / action/index.JS
- import { requestBegin, received, requestFailed } from './http3Steps'
- import toPromise from '../module/to-promise'
- // 微信小程序没有提供 Promise 版本的异步 API
- // 我封装了一个库, 把微信小程序异步 API 转化为 Promise, 用于处理 redux 中的异步 action
- // 项目地址: https://GitHub.com/tornoda/to-promise
- // 使用方法见 blog:https://www.cnblogs.com/looyulong/p/9471424.html
- const toPromiseWx = toPromise(wx)
- const request = toPromiseWx('request')
- // 这是一个同步的 action
- export const INCREASE = 'INCREASE'
- export const increase = {
- type: INCREASE
- }
- // 这是一个异步 action
- // 网络请求 action
- // 根据 redux 官网的介绍, 它应该是一个 Promise, 但是微信小程序没有提供 Promise 版本的异步 API, 需要使用上面提到的工具库
- export const GAME_LIST = '_GAME_LIST'
- export const fetch = (requestName, option) => {
- return (dispatch) => {
- dispatch(requestBegin(requestName))// 请求开始, 更新 state 状态
- return request(option)
- .then(
- (res) => { dispatch(received(requestName, res)); return res },// 请求成功, 把返回的信息在 state 中更新
- (err) => { dispatch(requestFailed(requestName, err)) }// 请求失败, 把失败的信息在 state 中更新
- )
- }
- }
编写处理 action 的 reducer
- // 项目根目录 / reducer/index.JS
- import { INCREASE } from '../actions/index'
- import { GAME_LIST } from '../actions/index'
- import { REQUSET_BEGIN, RECEIVED, REQUEST_END } from '../actions/http3Steps'
- import { combineReducers } from "../module/redux";
- // 这是处理本例子中同步 action 的 reducer
- export const disposeIncrease = (state = 0, action) => {
- switch (action.type) {
- case INCREASE:
- console.log('redux is worked')
- return state + 1
- default:
- return state
- }
- }
- // 这是处理本例中异步的 reducer
- const preState = {}
- export const disposeFetch = (state = preState, action) => {
- switch (action.type) {
- case REQUSET_BEGIN + GAME_LIST:
- return {
- ...state,
- status: 'REQUEST_BEGIN',
- }
- case RECEIVED + GAME_LIST:
- return {
- ...state,
- status: 'RECEIVED',
- res: action.res
- }
- case REQUEST_END + GAME_LIST:
- return {
- ...state,
- status: 'REQUEST_END',
- err: action.err
- }
- default:
- return state
- }
- }
- // 按照 state 的结构组合起来
- export default combineReducers({
- theIncreasingNo: disposeIncrease,
- asyncData: disposeFetch
- })
让 state 变化时自动更新 ui 视图
方法很简单, 在 page 的 index.JS 中的 onLoad 函数里面调用 store.subscribe() 方法监听局部 data.
- onLoad: function () {
- const _this = this
- // 在 onLoad 函数中订阅 state 的更新
- // 如果 state 变化, 对应 ui 就会更新
- subscribe(() => {
- const { asyncData: { status }, theIncreasingNo } = getState()
- _this.setData({
- syncData: `
请求状态:${status},
返回的数据请查看控制台
- `,
- number: theIncreasingNo
- })
- })
- }
触发动作, 发出 action, 改变 state
- //index.JS
- import { store } from '../../App'
- import { increase, fetch, GAME_LIST } from '../../actions/index'
- const { dispatch, subscribe, getState } = store
- Page({
- data: {
- syncData: 'Hello World',
- number: '0',
- },
- onLoad: function () {
- const _this = this
- // 发出一个异步 action
- dispatch(fetch(GAME_LIST, {
- url: 'http://open.douyucdn.cn/API/RoomApi/game'
- })).then((data) => { console.log(data) })
- // 在 onLoad 函数中订阅 state 的更新
- // 如果 state 变化, 对应 ui 就会更新
- subscribe(() => {
- const { asyncData: { status }, theIncreasingNo } = getState()
- _this.setData({
- syncData: `
请求状态:${status},
返回的数据请查看控制台
- `,
- number: theIncreasingNo
- })
- })
- },
- testSyncAction: function () {
- // 发出一个同步 action
- dispatch(increase)
- }
- })
如下图:
源文件
DEMO 地址 https://GitHub.com/tornoda/miniProgram-with-redux
实战项目
稍后上传, 敬请期待.
来源: https://www.cnblogs.com/looyulong/p/9709943.html