状态管理

okam 支持使用 redux 作为状态管理库,由于 vuexvue 是耦合的,暂时不支持在 okam 框架下使用。

!> 快应用 okam-core@0.4.8 开始支持

注意: 目前实现,在页面隐藏时候,组件的状态变更监听自动销毁,依赖原生自定义组件 pageLifetimes 提供的页面生命周期钩子 hideshow,因此有相应版本要求,具体可以查看微信小程序百度小程序,对于支付宝暂未有相应实现。

安装依赖

使用 redux 需要先安装相应的依赖:npm i redux --save,如果需要使用异步 Action ,还需要安装相应的中间件依赖,比如 redux-thunk 或者其它自己熟悉的中间件。

构建配置

framework 构建配置项增加 data redux 属性值,redux 依赖 data 扩展,因此需要一起配置。此外,需要把环境变量做下替换,使用 replacement 处理器。

  1. {
  2. framework: ['data', 'redux'],
  3. dev: {
  4. rules: [
  5. {
  6. match: '*.js',
  7. processors: [
  8. ['replacement', {'process.env.NODE_ENV': '"development"'}]
  9. ]
  10. }
  11. ]
  12. },
  13. prod: {
  14. rules: [
  15. {
  16. match: '*.js',
  17. processors: [
  18. ['replacement', {'process.env.NODE_ENV': '"production"'}]
  19. ]
  20. }
  21. ]
  22. }
  23. }

定义 Action

  1. // src/store/action.js
  2. export increment(value) {
  3. return {
  4. type: 'INCREMENT',
  5. value
  6. };
  7. }
  8. export decrement(value) {
  9. return {
  10. type: 'DECREMENT',
  11. value
  12. };
  13. }

定义 Reducer

  1. // src/store/reducer.js
  2. function increment(state, {value}) {
  3. state.count += value;
  4. return state;
  5. }
  6. function decrement(state, {value}) {
  7. state.count -= value;
  8. return state;
  9. }
  10. export default (state = {count: 0}, action) => {
  11. switch (action.type) {
  12. case 'INCREMENT':
  13. return increment(state, action);
  14. case 'DECREMENT':
  15. return decrement(state, action);
  16. default:
  17. return state;
  18. }
  19. };

定义 Store

  1. // src/store/index.js
  2. import {createStore} from 'redux';
  3. import rootReducer from './reducer';
  4. export default createStore(rootReducer);

入口脚本注入 Store

  1. // src/app.js
  2. import store from './store';
  3. export default {
  4. config: {},
  5. // 注入 store
  6. $store: store
  7. };

组件和 Store 数据连接

  1. // src/pages/index.okm#script
  2. import * as actions from '../store/action';
  3. export default {
  4. data: {
  5. num: 3,
  6. initCounter: 0
  7. },
  8. computed: {
  9. local() {
  10. return this.num;
  11. }
  12. },
  13. $store: { // 通过 `$store` 定义 store 跟组件数据关联
  14. // 定义 store computed 属性
  15. computed: ['count'], // this.count 等价于 store.getState().count
  16. computed: {
  17. myCount: 'count', // 定义 store 状态的别名,this.myCount 等价于 store.getState().count
  18. otherState(state) {
  19. return state.count + this.local + this.initCounter;
  20. }
  21. },
  22. // 定义 store mutation actions
  23. actions: actions, // this.increment(2), this.decrement(10);
  24. actions: [
  25. actions, // original actions
  26. {
  27. incr: 'increment', // this.incr(10) 等价于 store.dispatch(actions.increment(10))
  28. decr: 'decrement',
  29. op(type, value) { // this.op('INCREMENT', 3);
  30. // 不能访问组件实例
  31. return {type, value};
  32. }
  33. }
  34. ]
  35. }
  36. };

Store 实例访问

所有组件实例上下文都可以通过 this.$store 获取到对应的 store 实例:

  1. export default {
  2. config: {},
  3. data: {},
  4. created() {
  5. let store = this.$store;
  6. console.log(store.getState());
  7. }
  8. }

API

  • $fireStoreChange(): 如果你有多个页面引用了同一个 store,但某个页面隐藏情况下,通过另外一个页面更新了 store,想在重新显示之前隐藏的页面能够自动同步 store 数据变更,可以使用该 API。

    1. export default {
    2. config: {title: 'my page'},
    3. data: {},
    4. onShow() {
    5. this.$fireStoreChange(); // 可以在页面重新显示时候,重新同步该 API
    6. }
    7. }

使用注意

由于 store组件 数据连接是基于 computed 实现的,因此定义的 computed 属性不能跟现有冲突,其次通过定义 actions 来定义组件修改 store 的 action,同样定义的 action 方法不能跟组件实例定义的 method 冲突。

不允许外部直接修改 store 的 state,只能通过触发的 action 修改。

目前实现机制,会导致每次 store 变更,computed 数据会重新计算,对于列表型数据,每次变更都会导致整个列表数据重新 setData,因此如果列表数据量比较大,可能会有性能问题。

此外,对于 store state 变更,对于引用类型,不能直接修改原来对象,然后返回之前数据对象,必须返回一个新的数据对象,否则会导致视图状态没有得到变更。提示: 由于 微信小程序 实现机制问题,可能即便你返回的还是之前的引用对象,在 微信小程序 下,发现还是会自动更新视图,但是在 百度小程序支付宝小程序 是不会自动变更的。

  1. const removeTodo = (state, {id}) => {
  2. let found = findById(state, id);
  3. if (found === -1) {
  4. return state;
  5. }
  6. // 需要返回全新对象
  7. let newArr = [].concat(state);
  8. newArr.splice(found, 1);
  9. return newArr;
  10. // 错误实现: 直接返回之前的对象
  11. // state.splice(found, 1);
  12. // return state;
  13. };