对前端开发抽象形成 View,reducer,handle 三个主要概念的开发模式
- identity
- pack
identity 是数据挂载在 store 上的标识 key,必须是全局唯一的,不管在业务模式中的层级关系如何,挂载到 store 上之后只有一层,这样可以方便获取和更新,直接来说就是是 List 的形式,而不是 Tree 的形式,保证复杂度不会几何级增加
pack 是挂载在 store 时 identity 对应的内容的具体定义,包括 reducers,handles 和 sagas:
store 中具体数据载体的定义,挂载之后会默认生成更新 reducer 的 action,也支持按照原生 redux action 的定义
// 最简单的reducer定义,更新reducer的action系统会自动生成
export function xxxReducer(state = []) {
return state;
}
// redux reducer
export function xxxReducer(state = [], action) {
switch (action.type) {
case 'XXX_UPDATE':
return action.paylod;
default:
return state;
}
}
handle 是业务逻辑流程,比如初始化页面的流程,获取数据的流程等等,都可以通过定义 handle 完成,主要包括 reducer 数据更新的流程
handle 的基本形式是 generator 函数,与 store 的交互借鉴了 redux-saga 的思想,redux-saga 的 api 在里面都可以使用
更新 reducer 通过 setter 定义 reducer 的更新器,结合 modify 使用,使用与 redux-saga 的
select
API 相似,具体参考下面的代码和API
import { call, modify, all } from '@ixinwu-ngp/web-core';
/**
* handle中定义业务setter,通过指定identity与reducer key来更新
* @param {Object} setters 挂载reducer时在store上自动生成的
* @param {String} identity reducer标识
* @param {*} value reducer对应的更新数据
*/
const setDataLoading = (setters, identity, value) => setters[identity].dataLoading(value);
/**
* 业务handle
* @param {Object} props 调用handle时this.props的一个拷贝
* @param {String} objId 传递的自定义参数
*/
export function* xxxHandle(props, objId) {
const { identity } = props;
try {
// 结合modify使用setter,更新identity下挂载的指定reducer
yield modify(setDataLoading, identity, true);
// 其他业务逻辑
...
} catch (e) {
yield modify(setDataLoading, identity, false);
...
}
}
/**
* 初始化页面handle
* @param {Object} props 调用handle时this.props的一个拷贝
* @param {String} objId 传递的自定义参数
*/
export function* initPage(props, objId) {
try {
const result = yield call(getListData, props, objId);
// 直接返回更新当前identity下挂载的reducers
return {
...result,
};
} catch (e) {
...
}
}
原生的 redux-saga
获取全局实例(单例)
import core from '@ixinwu-ngp/web-core';
获取 store 实例
import core from '@ixinwu-ngp/web-core';
const store = core.store;
除了 redux 提供的 api 之外还有:
- injectReducers(identity, reducers)
- removeReducers(identity)
- injectSaga(identity, saga, ...args)
- removeSaga(identity)
配置 store
import { configureStore } from '@ixinwu-ngp/web-core';
// 各项参数与redux的createStore相同,以单个对象的不同属性传入
const store = configureStore({
// init reducers
reducers,
// init state
initialState,
// init middleware
middlewares,
});
挂载 pack
import { mount } from '@ixinwu-ngp/web-core';
/**
* @param {String} identity
* @param {Object} pack 结构为{ reducers = {...}, handles = {...}, sagas = {...} }
*/
mount(identity, pack);
});
卸载 pack
import { unmount } from '@ixinwu-ngp/web-core';
/**
* @param {String} identity
*/
unmount(identity, pack);
});
连接 React View、reducers 数据和 handles
使用方式与 react-dedux 的connect
使用相同,处理一下事务:
- 将 reducer 的数据通过 props 绑定到 React View(react-redux 的功能)
- 将 handles 通过 props 绑定到 React View
- 将 React View 的 props 作为 handle 的第一个参数props传入
import { connect } from '@ixinwu-ngp/web-core';
更新 reducer 数据
通过 modify 结合定义 setter 实现,参考代码:
// handles.js
import { modify } from '@ixinwu-ngp/web-core';
/**
* handle中定义业务setter,通过指定identity与reducer key来更新
* @param {Object} setters 挂载reducer时在store上自动生成的
* @param {String} identity reducer标识
* @param {*} value reducer对应的更新数据
*/
const aaaReducerSetter = (setters, identity, value) => setters[identity].aaaReducer(value);
export function* xxxHandle(props, objId) {
const { identity } = props;
try {
// 结合modify使用setter,更新identity下挂载的指定reducer
yield modify(setDataLoading, identity, true);
// 其他业务逻辑
...
} catch (e) {
yield modify(setDataLoading, identity, false);
...
}
}
这个包实现的是redex、react-redux和redux-saga的封装,并没有封装react,按照API的说明结合react可以更加方便的开发
更推荐的方式是使用@ixinwu-ngp/web-framework,基于这个包的功能进行了使用封装,快速构建应用