1.4.1 • Published 6 years ago
sinooa-redux-crud v1.4.1
sinooa-redux-crud
适用于中科软OA产品的CRUD业务的通用Redux实现。
sinooa-redux-crud实现:
- 业务的各种数据列表分页加载
- 业务数据的删除、新增、修改
- 草稿
- 删除、新增、修改与数据列表的同步
- 包括ActionTypes、Actions、Reducers、Sagas、Selectors
安装
先在项目中添加依赖
yarn add sinooa-redux-crud
或者
npm install --save sinooa-redux-crud
试用
采用redux管理状态,需要有ActionTypes、ActionCreators、reducer、saga和store。接下来,就用sinooa-redux-crud来实现redux状态管理。
首先通过create-react-app创建一个react应用,添加相关依赖,然后在这个demo项目中添加以下代码文件。
jfw.js
:
import { ActionTypes, ActionCreators, createReducers, createSagas } from 'sinooa-redux-crud';
import { create } from 'apisauce';
const http = create({
baseURL: '/api',
});
const moduleId = 'jfw';
const idPropertyName = 'id'; //业务数据中的id属性名
const listTypes = ['todos', 'related']; //列表类别
const baseUrl = '/spring/archives/out/jfw';
const actionTypes = new ActionTypes(moduleId, listTypes);
const actionCreators = new ActionCreators(moduleId, idPropertyName, listTypes);
const reducers = createReducers(moduleId, idPropertyName, listType);
const saga = createSagas(http, moduleId, baseUrl, idPropertyName, listType);
export { actionTypes, actionCreators, reducers, saga };
store.js
:
import { ActionTypes, ActionCreators, createReducers, createSagas } from 'sinooa-redux-crud';
import { createStore, applyMiddleware, compose, combineReducers } from 'redux';
import createSagaMiddleware from 'redux-saga';
import { create } from 'apisauce';
import { reducers, saga } from './jfw';
const sagaMiddleware = createSagaMiddleware();
const enhancer = compose(applyMiddleware(sagaMiddleware));
const store = createStore(combineReducers({
jfw: reducers,
}), enhancer);
sagaMiddle.run(rootSaga);
export default store;
components/JfwList.js
:
import React from 'react';
export default function({
items,
pageNo,
onRequestFetch,
}) {
return (
<div>
<button onClick={() => onRequestFetch(0) }>刷新</button>
<button onClick={() => onRequestFetch(pageNo + 1)}>加载下一页</buton>
<ul>{items.map(item => <li>{item.title}</li>)}</ul>
</div>);
}
containers/JfwList.js
:
import { connect } from 'react-redux';
import JfwList from '../components/JfwList';
import { actionCreators } from '../jfw';
const mapStateToProps = state => ({
items: state.jfw.todos.map(id => state.jfw.records[id]),
pageNo: state.jfw.todosPage.number,
});
const mapDispatchToProps = dispatch => ({
onRequestFetch: pageNo => dispatch(actionCreators.fetchTodos('userId', pageNo, 15))
});
export default connect(mapStateToProps, mapDispatchToProps)(JfwList);
App.js
:
import React from 'react';
import { Provider } from 'react-redux';
import JfwList from './containers/JfwList';
import store from './store';
export default function() {
return (<Provider store={store}>
<JfwList />
</Provider>);
}
规范示例
状态
一个crud业务(例如名称为jfw)的状态结构如下:
STATE_ROOT
|__ jfw
|___ records
|___ '1'
|___ id: '1'
|___ title: '开发sinooa-crud-redux@1.0.0'
|___ done: true
|___ '2'
|___ id: '2'
|___ title: '开发sinooa-workflow-redux@1.0.0'
|___ done: false
|___ '3'
|___ id: '3'
|___ title: '开发react-native-sinooa-workflow@1.0.0'
|___ done: false
|___ todos: ['2', '3']
|___ all: ['1', '2', '3']
|___ related: ['1', '2']
|___ draft: ['3']
|___ createStatus: 'DOING' | 'SUCCESS' | 'FAILURE' | 'NORMAL'
|___ createError: '创建失败的错误描述'
|___ deleteStatus: 'DOING' | 'SUCCESS' | 'FAILURE' | 'NORMAL'
|___ deleteError: '删除失败的错误描述'
|___ updateStatus: 'DOING' | 'SUCCESS' | 'FAILURE' | 'NORMAL'
|___ updateError: '更新失败的错误描述'
|___ fetchTodosStatus: 'FETCHING' | 'SUCCESS' | 'FAILURE' | 'NORMAL'
|___ fetchTodosError: '加载待办列表失败的描述'
|___ fetchTodosPageNo: 0
|___ todosPage
|___ number: 0 ---- 当前页数
|___ size: 15 ---- 一页包含项目的数量
|___ totalPages: 1 ---- 总页数
|___ totalElements: 3 ---- 总项目数目
|___ numberOfElements: 3 ---- 当前页包含项目的数量
|___ last: true ---- 最后一页
|___ first: true ---- 第一页
|___ todosFilterConditions: {} ----- 待办列表的过滤条件
|___ todosSort: [ ['createDate', 'desc'], ['updateDate', 'asc']] ------- 待办列表的排序设置
|___ fetchAllStatus: 'FETCHING' | 'SUCCESS' | 'FAILURE' | 'NORMAL'
|___ fetchAllError: '加载待办列表失败的描述'
|___ fetchAllPageNo: 0
|___ allPage
|___ number: 0 ---- 当前页数
|___ size: 15 ---- 一页包含项目的数量
|___ totalPages: 1 ---- 总页数
|___ totalElements: 3 ---- 总项目数目
|___ numberOfElements: 3 ---- 当前页包含项目的数量
|___ last: true ---- 最后一页
|___ first: tru ---- 第一页
|___ allFilterConditions: {} ----- 全部列表的过滤条件
|___ allSort: [ ['createDate', 'desc'], ['updateDate', 'asc']] ------- 全部列表的排序设置
|___ fetchRelatedStatus: 'FETCHING' | 'SUCCESS' | 'FAILURE' | 'NORMAL'
|___ fetchRelatedError: '加载待办列表失败的描述'
|___ fetchRelatedPageNo: 0
|___ relatedPage
|___ number: 0 ---- 当前页数
|___ size: 15 ---- 一页包含项目的数量
|___ totalPages: 1 ---- 总页数
|___ totalElements: 3 ---- 总项目数目
|___ numberOfElements: 3 ---- 当前页包含项目的数量
|___ last: true ---- 最后一页
|___ first: true ---- 第一页
|___ relatedFilterConditions: {} ----- 待办列表的过滤条件
|___ relatedSort: [ ['createDate', 'desc'], ['updateDate', 'asc']] ------- 待办列表的排序设置
关于业务的数据是存储在records
中的,这是一个业务主键id与业务数据对应的map。
列表中存储的是业务主键id,如todos: ['2', '3']
,related: ['1', '2']
。
动作
动作类型
以局发文(jfw)为例:
import { ActionTypes } from 'sinooa-crud-workflow';
const actionTypes = new ActionTypes('jfw');
获取方式 | 动作类型 | 动作类型描述 |
---|---|---|
actionTypes.createStart | JFW_CREATE_START | 开始创建局发文 |
actionTypes.createSuccess | JFW_CREATE_SUCCESS | 创建局发文成功 |
actionTypes.createFailure | JFW_CREATE_FAILURE | 创建局发文失败 |
actionTypes.resetCreateStatus | JFW_RESET_CREATE_STATUS | 重置创建状态 |
actionTypes.updateStart | JFW_UPDATE_START | 开始更新局发文 |
actionTypes.updateSuccess | JFW_UPDATE_SUCCESS | 更新局发文成功 |
actionTypes.updateFailure | JFW_UPDATE_FAILURE | 更新局发文失败 |
actionTypes.resetUpdateStatus | JFW_RESET_UPDATE_STATUS | 重置更新状态 |
actionTypes.deleteStart | JFW_DELETE_START | 开始删除局发文 |
actionTypes.deleteSuccess | JFW_DELETE_SUCCESS | 删除局发文成功 |
actionTypes.deleteFailure | JFW_DELETE_FAILURE | 删除局发文失败 |
actionTypes.resetDeleteStatus | JFW_RESET_DELETE_STATUS | 重置删除状态 |
actionTypes.fetchRecordStart | JFW_FETCH_RECORD_START | 开始加载单个数据 |
actionTypes.fetchRecordSuccess | JFW_FETCH_RECORD_SUCCESS | 加载单个数据成功 |
actionTypes.fetchRecordFailure | JFW_FETCH_RECORD_FAILURE | 加载单个数据失败 |
actionTypes.resetFetchRecordStatus | JFW_RESET_FETCH_RECORD_STATUS | 重置加载单个数据的状态 |
actionTypes.fetchTodosStart | JFW_FETCH_TODOS_START | 开始加载待办列表 |
actionTypes.fetchTodosSuccess | JFW_FETCH_TODOS_SUCCESS | 加载待办列表成功 |
actionTypes.fetchTodosFailure | JFW_FETCH_TODOS_FAILURE | 加载待办列表失败 |
actionTypes.resetFetchTodosStatus | JFW_RESET_FETCH_TODOS_STATUS | 重置加载待办列表的状态 |
actionTypes.fetchAllStart | JFW_FETCH_ALL_START | 开始包含所有数据的列表 |
actionTypes.fetchAllSuccess | JFW_FETCH_ALL_SUCCESS | 加载包含所有数据的列表成功 |
actionTypes.fetchAllFailure | JFW_FETCH_ALL_FAILURE | 加载包含所有数据的列表失败 |
actionTypes.resetFetchAllStatus | JFW_RESET_FETCH_ALL_STATUS | 重置加载包含所有数据的列表状态 |
actionTypes.fetchReleatedStart | JFW_FETCH_RELATED_START | 开始加载相关数据列表 |
actionTypes.fetchRelatedSuccess | JFW_FETCH_RELATED_SUCCESS | 加载相关数据列表成功 |
actionTypes.fetchRelatedFailure | JFW_FETCH_RELATED_FAILURE | 加载相关数据列表失败 |
actionTypes.resetFetchRelatedStatus | JFW_RESET_FETCH_RELATED_STATUS | 重置加载相关数据列表状态 |
actionTypes.fetchDraftStart | JFW_FETCH_DRAFT_START | 开始加载草稿数据列表 |
actionTypes.fetchDraftSuccess | JFW_FETCH_DRAFT_SUCCESS | 加载草稿数据列表成功 |
actionTypes.fetchDraftFailure | JFW_FETCH_DRAFT_FAILURE | 加载草稿数据列表失败 |
actionTypes.resetFetchDraftStatus | JFW_RESET_FETCH_DRAFT_STATUS | 重置加载草稿列表状态 |
actionTypes.resetRecordStatus | JFW_RESET_RECORD_STATUS | 重置单条业务数据相关的状态 |
动作创建器
以局发文(jfw)为例:
import { ActionCreators } from 'sinooa-crud-redux';
const actionCreators = new ActionCreators('jfw', 'id');
动作创建器 | 动作类型 | 动作类型描述 |
---|---|---|
actionCreators.createStart(record) | JFW_CREATE_START | 开始创建局发文 |
actionCreators.createSuccess(record) | JFW_CREATE_SUCCESS | 创建局发文成功 |
actionCreators.createFailure(error) | JFW_CREATE_FAILURE | 创建局发文失败 |
actionCreators.resetCreateStatus() | JFW_RESET_CREATE_STATUS | 重置创建状态 |
actionCreators.updateStart(record) | JFW_UPDATE_START | 开始更新局发文 |
actionCreators.updateSuccess(record) | JFW_UPDATE_SUCCESS | 更新局发文成功 |
actionCreators.updateFailure(record) | JFW_UPDATE_FAILURE | 更新局发文失败 |
actionCreators.resetDeleteStatus() | JFW_RESET_DELETE_STATUS | 重置删除状态 |
actionCreators.deleteStart(id) | JFW_DELETE_START | 开始删除局发文 |
actionCreators.deleteSuccess(id) | JFW_DELETE_SUCCESS | 删除局发文成功 |
actionCreators.deleteFailure(error) | JFW_DELETE_FAILURE | 删除局发文失败 |
actionCreators.resetDeleteStatus() | JFW_RESET_DELETE_STATUS | 重置删除状态 |
actionCreators.fetchRecordStart(id) | JFW_FETCH_RECORD_START | 开始加载单个数据 |
actionCreators.fetchRecordSuccess(record) | JFW_FETCH_RECORD_SUCCESS | 加载单个数据成功 |
actionCreators.fetchRecordFailure(error) | JFW_FETCH_RECORD_FAILURE | 加载单个数据失败 |
actionCreators.resetFetchRecordStatus() | JFW_RESET_FETCH_RECORD_STATUS | 重置加载单个数据的状态 |
actionCreators.fetchTodosStart(userId, pageNo, pageSize, filterCondition?, sort?) | JFW_FETCH_TODOS_START | 开始加载待办列表 |
actionCreators.fetchTodosSuccess(page) | JFW_FETCH_TODOS_SUCCESS | 加载待办列表成功 |
actionCreators.fetchTodosFailure(error) | JFW_FETCH_TODOS_FAILURE | 加载待办列表失败 |
actionCreators.resetFetchTodosStatus() | JFW_RESET_FETCH_TODOS_STATUS | 重置加载待办列表的状态 |
actionCreators.fetchAllStart(userId, pageNo, pageSize, filterCondition?, sort?) | JFW_FETCH_ALL_START | 开始包含所有数据的列表 |
actionCreators.fetchAllSuccess(page) | JFW_FETCH_ALL_SUCCESS | 加载包含所有数据的列表成功 |
actionCreators.fetchAllFailure(error) | JFW_FETCH_ALL_FAILURE | 加载包含所有数据的列表失败 |
actionCreators.resetFetchAllStatus() | JFW_RESET_FETCH_ALL_STATUS | 重置加载包含所有数据的列表状态 |
actionCreators.fetchReleatedStart(userId, pageNo, pageSize, filterCondition?, sort?) | JFW_FETCH_RELATED_START | 开始加载相关数据列表 |
actionCreators.fetchRelatedSuccess(page) | JFW_FETCH_RELATED_SUCCESS | 加载相关数据列表成功 |
actionCreators.fetchRelatedFailure(error) | JFW_FETCH_RELATED_FAILURE | 加载相关数据列表失败 |
actionCreators.resetFetchRelatedStatus() | JFW_RESET_FETCH_RELATED_STATUS | 重置加载相关数据列表状态 |
actionCreators.fetchDraftStart(userId, pageNo, pageSize, filterCondition?, sort?) | JFW_FETCH_DRAFT_START | 开始加载草稿数据列表 |
actionCreators.fetchDraftSuccess(page) | JFW_FETCH_DRAFT_SUCCESS | 加载草稿数据列表成功 |
actionCreators.fetchDraftFailure(error) | JFW_FETCH_DRAFT_FAILURE | 加载草稿数据列表失败 |
actionCreators.resetFetchDraftStatus() | JFW_RESET_FETCH_DRAFT_STATUS | 重置加载草稿列表状态 |
actionTypes.resetRecordStatus(recordId) | JFW_RESET_RECORD_STATUS | 重置单条业务数据相关的状态 |
说明:
filterCondition
- 表示过滤条件。形如{ title: '标题' }
sort
- 指定排序规则。形如[['startDate', 'desc'], ['endDate, 'asc']]
API说明
创建reducer
import { createReducer } from 'sinooa-redux-crud';
const moduleId = 'fawen';
const idPropertyName = 'id';
const listTypes = [{
name: 'todos',
onlySaveCurrentPageData: true,
saveDataToRecords: true,
}, 'related', 'all'];
const reducer = createReducer(moduleId, idPropertyName, listTypes);
重点介绍一下listTypes
的配置。listTypes
是用来定义数据列表的。它是一个数组。数据中包含对数据列表的定义,这些定义包括:
name
- 数据列表的名称onlySaveCurrentPageData
- 是否只存储当前加载页的数据。默认为false
,表示存储所有页的数据。saveDataToRecords
- 保存数据到公共的records
中。默认为true
。onDeleteRecord
- 当发生删除操作时,列表需要做的响应onUpdateRecord
- 当发生数据更新操作时,列表需要做的响应onCreateRecord
- 当创建数据时,列表需要做出的响应