实现
该案例是以中间件调用 nodejs 的公共接口,实现一个数据列表。
源码下载:
用户名和密码都为空
源码下载后执行下面步骤例可查看效果
npm install
npm start
Redux 中间件的问题之作用域
在 Redux 中使用中间件可以解决很多问题,但也会有个致命的问题,那就是在同一个组件中多次调用同一个组件,那就会造成作用域污染。
本案例中是这样的场景:
- 现在要实现在组件
cnode
中动态加载数据,在该组件中还会有一个输入框,点击时弹窗动态加载一个数据列表,双击数据列表进行填充到对应的输入框中 - 有一个组件
datagrid
,用于动态加载数据,ajax 加载使用了中间件。 - 有一个组件
modal
,该组件用到弹窗加载一个数据列表datagrid
- 在组件
cnode
中调用了组件datagrid
,<Datagrid config={this.props.cnode.config}/>
- 在组件
cnode
中同时调用了组件modal
,而组件modal
又调用了组件datagrid
。 - 这个时候两个
datagrid
的数据源就会冲突,后面加载的数据冲突了前面加载的。 - 解决方案是在数据源中对数据源作用域隔离
对象作用域隔离
每次调用组件datagrid
时给一个别名name
,别名不能重复,用于作用域隔离
static defaultProps = { cnode: { config: { url: 'https://cnodejs.org/api/v1/topics', data: {page: 1, limit: 10}, cols: ['title', 'reply_count', 'top', 'create_at', 'last_reply_at'], name: 'cnode' } }, modal: { config: { type: 'datagrid', url: 'https://cnodejs.org/api/v1/topics', data: {page: 3, limit: 5}, cols: ['title'], name: 'modal' } }}
在 Action
中将别名name
派发到中间件
export function refresh(_config){ return { types: [constants.Requesting, constants.Requested, constants.RequestError], url: _config.url, method: _config.method || 'get', data: _config.data || {}, name: _config.name }}
在中间件将别名name
一派发到Reducer
let _action = { type: constants.Requested, name, result: res.data}dispatch(_action)
在Reducer
中兼容有别名和没别名的情况,如果有别名,就将数据源作用域隔离
if(action.name){ _state[action.name] = _state[action.name] || {}; _state[action.name].dataset = action.result;} else { _state.dataset = action.result;}
在DatagridComponent
中判断是否有别名,兼容有别名和没别名的情况,分别操作不同的数据源
let ds = this.props.dataset;let name = this.props.config.name;if(name){ ds = ds[name] ? ds[name].dataset : []} else { ds = ds.dataset || [];}