react相关库
很多新手去学习react总会先去官网撸一遍教程,然后找案例去实操,但是忽略了实际项目里用的一些库是react官方文档中没有的。比如下面说到的
先来做一些概念扫盲:
-
redux-thunk: redux中间件,用来改造store.dispatch, 使其可以接收函数作为参数。通常可以它其作为异步的一种解决方案。
-
redux-saga: 管理应用副作用的库,即管理异步获取数据、访问浏览器缓存相关操作, 从名字上来看就跟状态相关。redux-saga与redux-thunk相比,他们都是redux的中间件,但redux-saga是通过 ES6中的 Generator 来实现异步。
-
dva: 一个基于 redux 和 redux-saga 的数据流方案,然后为了简化开发体验,dva 还额外内置了 react-route 和 fetch,所以也可以理解为一个轻量级的应用框架
-
umi: 企业级开发框架,类似于资源整合,你要快速启动项目的话,就不需要单独去安装react、react-router等库,同时提供了可配置router,可与dva数据流深度融合。
-
antd: 蚂蚁金服出的基于umi的UI组件库。
一些比较重要的点
1. redux-thunk的使用
// 导入
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import reducer from './reducers';
// Note: this API requires redux@>=3.1.0
const store = createStore(
reducer,
applyMiddleware(thunk)
);
使用示例
const fetchPosts = postTitle => (dispatch, getState) => {
dispatch(requestPosts(postTitle));
return fetch(`/some/API/${postTitle}.json`)
.then(response => response.json())
.then(json => dispatch(receivePosts(postTitle, json)));
};
};
// 使用方法一
store.dispatch(fetchPosts('reactjs'));
// 使用方法二
store.dispatch(fetchPosts('reactjs')).then(() =>
console.log(store.getState())
);
2. redux-saga的使用
// 导入
import {createStore, combineReducers, applyMiddleware} from "redux";
import createSagaMiddleware from 'redux-saga'
import {userReducer} from "./userReducer";
import loginSaga from "../action/loginSaga";
const sagaMiddleware = createSagaMiddleware();
const store = createStore(
combineReducers({user: userReducer}),
applyMiddleware(sagaMiddleware)
)
sagaMiddleware.run(loginSaga);
调用
export default connect(
({user}) => ({user}),
{
login: userInfo => ({type: "loginSaga",
payload: userInfo})
}
)(
class LoginPage extends Component {
//...
}
);
action/loginSaga.js
// 调⽤异步操作 call、fork
// call 是⼀个会阻塞的 Effect。即 Generator 在调⽤结束之前不能执⾏或处理任何其他事情。
// fork 是⽆阻塞型调⽤,当我们fork⼀个任务,任务会在后台启动,
// 调⽤者也可以继续它⾃⼰的流程,⽽不⽤等待被 fork 的任务结束。
// 状态更新 (dispatch) put
// 做监听 take
import {call,fork,put,take} from "redux-saga/effects";
import LoginService from "../service/login";
// worker saga
function* loginHandle(action) {
// 调⽤异步操作 call
yield put({type: "LOGIN_REQUEST"});
try {
const res1 = yield call(LoginService.login, action.payload);
const res2 = yield call(LoginService.getMoreUserInfo, res1);
yield put({type: "LOGIN_SUCCESS", payload: {...res1, ...res2}});
} catch (err) {
yield put({type: "LOGIN_FAILURE", payload: err});
}
}
// watcher saga
function* loginSaga() {
yield takeEvery("loginSaga", loginHandle);
}
export default loginSaga;
const takeEvery = (pattern, saga, ...args) => fork(function*() {
while (true) {
const action = yield take(pattern);
yield fork(saga, ...args.concat(action));
}
});
3. dva对redux数据流的影响
4. dva的使用
最简结构
// 创建应用
const app = dva();
// 注册 Model
app.model({
namespace: 'count', //命名空间
state: 0,
reducers: {
add(state) { return state + 1 },
},
effects: {
*addAfter1Second(action, { call, put }) {
yield call(delay, 1000);
yield put({ type: 'add' });
},
},
});
// 注册视图
app.router(() => <ConnectedApp />);
// 启动应用
app.start('#root');
5. react-redux、redux中间件与dva关系
借用dva官方文档的数据流图示来理清他们之间的关系
react-redux数据流
redux 中间件数据流
dva数据流
6. umi框架的架构
从图中实现层 umi-core 可以看出它是 路由+插件+ui 的整合。
7. umi和dva、roadhog的关系
- roadhog 是基于 webpack 的封装工具,目的是简化 webpack 的配置
- umi 可以简单地理解为 roadhog + 路由,思路类似 next.js/nuxt.js,辅以一套插件机制,目的是通过框架的方式简化 React 开发
- dva 目前是纯粹的数据流,和 umi 以及 roadhog 之间并没有相互的依赖关系,可以分开使用也可以一起使用。
总结
在这里,还是希望大家在学习 react 的过程中,不要仅局限于官方给出的API,还要多去了解下实际项目中的其他方案,毕竟别人把轮子已经造好了。