React 图解
转载:https://www.yuque.com/flying.ni/the-tower/tvzasn
按照 React 官方指导意见, 如果多个 Component
之间要发生交互, 那么状态(即: 数据)就维护在这些 Component
的最小公约父节点上, 也即是 <App/><TodoList/> <Todo/>
以及<AddTodoBtn/>
本身不维持任何 state, 完全由父节点<App/>
传入 props
以决定其展现, 是一个纯函数的存在形式, 即: Pure Component
Redux 图解
与图一相比, 几个明显的改进点:
状态及页面逻辑从 <App/>
里面抽取出来, 成为独立的 store
, 页面逻辑就是 reducer
<TodoList/>
及<AddTodoBtn/>
都是 Pure Component
, 通过 connect
方法可以很方便地给它俩加一层 wrapper
从而建立起与store
的联系: 可以通过 dispatch
向 store
注入 action
, 促使 store
的状态进行变化, 同时又订阅了 store
的状态变化, 一旦状态有变, 被 connect
的组件也随之刷新
使用 dispatch
往 store
发送 action
的这个过程是可以被拦截的, 自然而然地就可以在这里增加各种 Middleware
, 实现各种自定义功能, eg: logging
这样一来, 各个部分各司其职, 耦合度更低, 复用度更高, 扩展性更好
图解Saga
上面说了, 可以使用 Middleware
拦截 action
, 这样一来异步的网络操作也就很方便了, 做成一个 Middleware
就行了, 这里使用 redux-saga
这个类库, 举个栗子:
- 点击创建
Todo
的按钮, 发起一个type == addTodo
的action
saga
拦截这个action
, 发起 http 请求, 如果请求成功, 则继续向reducer
发一个type == addTodoSucc
的action
, 提示创建成功, 反之则发送type == addTodoFail
的action
即可
图解Dva
有了前面的三步铺垫, Dva
的出现也就水到渠成了, 正如 Dva
官网所言, Dva
是基于 React + Redux + Saga
的最佳实践沉淀, 做了 3 件很重要的事情, 大大提升了编码体验:
- 把
store
及saga
统一为一个model
的概念, 写在一个 js 文件里面 - 增加了一个
Subscriptions
, 用于收集其他来源action
, eg: 键盘操作 model
写法很简约, 类似于DSL
或者RoR
,coding
快得飞起✈️
app.model({
namespace: 'count',
state: {
record: 0,
current: 0,
},
reducers: {
add(state) {
const newCurrent = state.current + 1;
return { ...state,
record: newCurrent > state.record ? newCurrent : state.record,
current: newCurrent,
};
},
minus(state) {
return { ...state, current: state.current - 1};
},
},
effects: {
*add(action, { call, put }) {
yield call(delay, 1000);
yield put({ type: 'minus' });
},
},
subscriptions: {
keyboardWatcher({ dispatch }) {
key('⌘+up, ctrl+up', () => { dispatch({type:'add'}) });
},
},
});