前言
刚接触 React 的时候, 有人感叹这不就是当年的 JSP 吗? 直接用代码生成 html, 两者混在一起, 还真有不少人喜欢把事件响应和业务逻辑都写在 component 里面, 看起来就头疼. 当年的 JSP 已经被 MVC 所终结, 我们可以借鉴 MVC 的思想让 React-Redux 的代码好写又好看.
先回顾一下 MVC 思想, 如下图:
用户的请求先由 Controller 进行处理, 处理后的数据放入 Model,View 根据 Model 的数据渲染界面呈现在用户面前.
React-Redux 中应用 MVC
1. Model 对应 Redux store
Redux store 由几个数据模块组成, 每个模块中的数据在一组页面或者一个业务流程中使用.
redux/rootReducer.JS
- import {reducer as common} from './commonAction'
- import {reducer as online} from './onlineAction'
- export default combineReducers({
- common,
- online,
- })
2. View 对应 React component
Component 将数据呈现出来, 要尽可能地只做页面显示, 其它代码一概抽离, 例如:
login/index.JS
- import {actions} from './action';
- class Login extends Component {
- componentWillMount() {
- this.props.clearSession();
- }
- render() {
- const p = this.props;
- return (
- <div className="form">
- <div className="input-group">
- <label>User Name</label>
- <input type="text" value={p.s.username} onChange={e=>p.updateFormValue({username: e.target.value})}>
- </div>
- <div className="input-group">
- <label>Password</label>
- <input type="password" value={p.s.password} onChange={e=>p.updateFormValue({password: e.target.value})}>
- </div>
- <div className="input-group">
- <button type="button" className="btn btn-block" disabled={!p.s.loginReady} onClick={p.submitLogin}>Login</button>
- </div>
- </div>
- )
- }
- }
- export default connect(
- store => ({ s: store.online }),
- { ...actions }
- )(Login);
3. Controller 对应 action,reducer
store 中的每个模块都有自己的 reducer 负责更新数据
redux/onlineAction.JS
- const types = {
- UPDATE_VALUE: 'ONLINE/UPDATE_VALUE',
- }
- export const actions = {
- updateValue: values => (dispatch, getStore) => {
- dispatch({type: types.UPDATE_VALUE, ...values});
- },
- }
- const initStore = {
- username: '',
- password: '',
- }
- export const reducer = (store={...initStore}, action) => {
- switch (action.type) {
- case types.UPDATE_VALUE:
- return {...store, ...action};
- default:
- return {...store};
- }
- }
把负责更新数据的 action type,action,reducer 合并成一个文件. 有些教程说, 每个变量都要一个特定的 action type,action creator 和 reducer 中的 case. 在我看来是没有意义的, 一个数据更新 action 就够模块里面所有变量使用了, 而且可以一次更新多个变量, 在接收后台数据时提高效率.
每个页面都有在自己的 action, 处理自己的事件响应和业务逻辑. 当需要时就调用模块级别的 action 来更新数据.
login/action.JS
- import {actions as onlineActions} from '../redux/onlineAction';
- export const actions = {
- updateFormValue: value => (dispatch, getStore) => {
- dispatch(onlineActions.updateValue(value));
- dispatch(actions.verifyValue());
- },
- verifyValue: () => (dispatch, getStore) => {
- const {username, password} = getStore().online;
- let loginReady = username.length>= 6;
- loginReady = loginReady && password.length>= 6;
- dispatch(onlineActions.updateValue(loginReady));
- },
- submitLogin: () => (dispatch, getStore) => {
- const {username, password} = getStore().online;
- // submit data to server ...
- }
- }
这里讨论了一种 React-Redux 项目的参考编码风格, 让代码看起来有 MVC 感觉, 好写好看.
另外, thunk 只是入门级的中间件, 对自己有要求的同学应该去学习一下 saga.
来源: http://www.bubuko.com/infodetail-3102107.html