原生小程序使用redux设置状态管理

2021年4月21日 25点热度 0人点赞 0条评论

微信小程序没有提供Promise版本的异步api;把微信小程序异步api转化为Promise,用于处理redux中的异步action;把微信小程序原生网络请求 request 转换为 promise,toPromise.js

const toPromise = (wx) => {
  return (method) => {
    return (option) => {
      return new Promise ((resolve, reject) => {
        wx[method]({
          ...option,
          success: (res) => { resolve(res) },
          fail: (err) => { reject(err) }
        })
      })
    }
  }
}
export default toPromise

设置 http 请求的三个状态,"开始请求"、"收到请求"和"请求失败"。http3Steps.js

export const REQUSET_BEGIN = 'REQUEST_BEGIN'; // 开始网络请求
export const RECEIVED = 'RECEIVED'; //  收到请求
export const REQUEST_FAILED = 'REQUEST_FAILED'; // 请求失败
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.js

import {
  requestBegin,
  received,
  requestFailed
} from './http3Steps'
import toPromise from './toPromise.js'
const toPromiseWx = toPromise(wx)
const request = toPromiseWx('request')

//网络请求action
//根据redux官网的介绍,它应该是一个Promise,但是微信小程序没有提供Promise版本的异步api,需要使用上面提到的工具库

export const fetch = (requestName, option) => {
  return (dispatch) => {
    dispatch(requestBegin(requestName)) //请求开始,更新state状态
    if(requestName=='_USER_LOGOUT') {
      // 用户退出登录时,清空缓存数据
      dispatch(requestFailed(requestName, "退出登录"));
      return;
    };
    return request(option)
      .then(
        (res) => {
          dispatch(received(requestName, res.data.payload));
          return res
        }, //请求成功,把返回的信息在state中更新
        (err) => {
          dispatch(requestFailed(requestName, err))
        } //请求失败,把失败的信息在state中更新
      )
  }
}

export const FZ_CONFIG_DATA = '_FZ_CONFIG_DATA'; // 复诊的配置信息
export const USER_INFO_DATA = "_USER_INFO_DATA"; // 用户信息
export const NEW_PRESCRIPTION = "_NEW_PRESCRIPTION"; // 最新处方
export const GET_BANNER = "_GET_BANNER"; // 首页的banner
export const USER_LOGOUT = "_USER_LOGOUT"; // 推出登陆

这里可以把定义的常量单独放在另一个文件里。在电脑本地创建一个空的文件夹,然后安装 redux、redux-thunk 和 redux-logger。在 node_modules 中选出对应 redux、redux-thunk 和 redux-logger 文件夹下的 dist 文件中的 redux.js、redux-thunk.js、redux-logger.js 复制到小程序项目下的 modules 文件夹内。

新建文件reducer.js

import { FZ_CONFIG_DATA } from './action.js' // 常量
import { REQUSET_BEGIN, RECEIVED, REQUEST_END } from './action.js'
import { combineReducers } from "../module/redux";

//这是处理本例中异步的reducer
const preState = {}

// 平台的配置数据
export const disposeFetch = (state = preState, action) => {
  switch (action.type) {
    case REQUSET_BEGIN + FZ_CONFIG_DATA:
      return {
        ...state,
        status: 'REQUEST_BEGIN',
      }
    case RECEIVED + FZ_CONFIG_DATA:
      return {
        ...state,
        status: 'RECEIVED',
        res: action.res
      }
    case REQUEST_END + FZ_CONFIG_DATA:
      return {
        ...state,
        status: 'REQUEST_END',
        err: action.err
      }
    case REQUSET_BEGIN + USER_LOGOUT:
      return {
        status: 'USER_LOGOUT',
      }
    default:
      return state
  }
}
// 用户信息
export const disposeUserInfo = (state = preState, action) => {
  switch (action.type) {
    case REQUSET_BEGIN + USER_INFO_DATA:
      return {
        ...state,
        status: 'REQUEST_BEGIN',
      }
    case RECEIVED + USER_INFO_DATA:
      return {
        ...state,
        status: 'RECEIVED',
        res: action.res
      }
    case REQUEST_END + USER_INFO_DATA:
      return {
        ...state,
        status: 'REQUEST_END',
        err: action.err
      }
    case REQUSET_BEGIN + USER_LOGOUT:
      wx.removeStorageSync('tokenId')
      wx.removeStorageSync('userData')
      wx.removeStorageSync('openid')
      return {
        status: 'USER_LOGOUT',
      }
    default:
      return state
  }
}
// 首页的最新数据
export const disposeNewPrescription = (state = {}, action) => {
  console.log(action)
  switch (action.type) {
    case REQUSET_BEGIN + NEW_PRESCRIPTION:
      return {
        ...state,
        status: 'REQUEST_BEGIN',
      }
    case RECEIVED + NEW_PRESCRIPTION:
      return {
        ...state,
        status: 'RECEIVED',
        res: action.res.list
      }
    case REQUEST_END + NEW_PRESCRIPTION:
      return {
        ...state,
        status: 'REQUEST_END',
        err: action.res
      }
    case REQUSET_BEGIN + USER_LOGOUT:
      return {
        status: 'USER_LOGOUT',
      }
    default:
      return state
  }
}
// 首页的banner数据
export const disposeBanner = (state = {}, action) => {
  switch (action.type) {
    case REQUSET_BEGIN + GET_BANNER:
      return {
        ...state,
        status: 'REQUEST_BEGIN',
      }
    case RECEIVED + GET_BANNER:
      return {
        ...state,
        status: 'RECEIVED',
        res: action.res
      }
    case REQUEST_END + GET_BANNER:
      return {
        ...state,
        status: 'REQUEST_END',
        err: action.err
      }
    default:
      return state
  }
}
//按照state的结构组合起来
export default combineReducers({
  asyncData: disposeFetch, // 平台的配置信息
  userData: disposeUserInfo, // 用户信息
  newPrescription: disposeNewPrescription, // 首页的最新数据
  banner: disposeBanner, // 首页的banner
})

最后在 app.js 中添加 store 相关的代码,或者是单独创建 store.js 文件也可以;

app.js

import reducer from './reducer.js'
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({
...
})

之所以在小程序中引入 redux 来做状态管理,无非就是在小程序频繁切换的几个页面中减少部分的网络请求,在性能上得到一定的优化。例如在首页中引入 redux:

home.js

import {
  store
} from '../../app';
import {
  fetch,
  FZ_CONFIG_DATA,
  USER_INFO_DATA,
  NEW_PRESCRIPTION,
  GET_BANNER,
} from '../../action/index';
const {
  dispatch,
  subscribe,
  getState
} = store;

Page({
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function () {
    const store_data = store.getState().userData;
    console.log("redux======",store_data)
    //在onLoad函数中订阅state的更新
    //如果state变化,对应ui就会更新
    subscribe(() => {
      const {
        asyncData: {
          status
        }
      } = getState();
    });

// 获取用信息
dispatch(fetch(USER_INFO_DATA, {
      url: serverUrl + "/ncmsSysXcxuser/login",
      data: {
        openid: wx.getStorageSync('openid')
      },
      header: {
        'content-type': 'application/x-www-form-urlencoded',
        "tokenid": wx.getStorageSync("tokenId")
      },
      method: "POST",
    })).then((result) => {
        console.log(result)
    })
  },
})

这就是原生小程序引入 redux 的流程。

读心悦

读心,读自己!

文章评论