在react可以使用redux包来创建一个数据仓库。
1.下载redux包:
在项目的根目录下,打开命令窗口,输入以下命令:
yarn add redux
2.创建仓库:
在src目录下,创建一个store文件夹,在其文件夹内创建一个index.js。
import { createStore, combineReducers, applyMiddleware } from "redux";
import categoryReducer, { CategoryActions } from './category.js';
import productReducer, { ProductActions } from './product.js';
import cartReducer, { CartActions } from './cart.js';
// 先想好仓库结构,每个子仓库的结构。
// 总reducer
const reducer = combineReducers({
category: categoryReducer,
product: productReducer,
cart: cartReducer
});
const store = createStore(reducer);
export default store;
// 统一导入各自仓库中的ActionsCreate再统一导出。
export {
CategoryActions,
ProductActions,
CartActions
};
其子仓库代码为:
import http from '../utils/http';
// 子reducer
const initState = { listMain: [], listSub: [] };
const ACTIONS = {
MAIN: Symbol(),
SUB: Symbol()
};
// action creator作用是:让组件和仓库通信更优雅
export const CategoryActions = {
assignListMain: () => async ({ dispatch, getState }) => {
// getState调用可以拿到当前仓库的state
let result = await http('/category/list/0');
dispatch({ type: ACTIONS.MAIN, payload: result });
},
assignListSub: fid => async ({ dispatch, getState }) => {
let result = await http('/category/list/' + fid);
dispatch({ type: ACTIONS.MAIN, payload: result });
}
};
const reducer = function(state = initState, action) {
const { type, payload } = action;
switch(type) {
case ACTIONS.MAIN:
return Object.assign({}, state, { listMain: [] });
case ACTIONS.SUB:
return Object.assign({}, state, { listSub: [] });
default:
return state;
}
};
export default reducer;
reducer函数的特点:
1.上一次return的结果,将会作为下一个reducer函数调用的第一个参数。
2.创建一个reducer仓库对象,reducer函数第一次调用时,可以设置一个默认值,表示state的初始状态。不过第一次调用时,第二个参数是没有的,后续的reducer函数调用时,会将第二个参数传过来,reducer函数会根据内部action,返回一个新的state,相当于仓库更新了。
3.action对象:如果一个对象有一个type属性值是字符串。redux认为它是action对象。
3.下载redux-thunk包:
为了使仓库的dispatch方法能够接受函数作为参数。将异步耗时的ajax代码放到dispatch的参数函数中。需要下载redux-thunk包。
yarn add redux-thunk
4.redux-thunk包使用:
dispatch函数默认只能接收actions对象,不能接收函数作为对象,所以我们要用第三方包redux-thunk来增强仓库的dispatch方法,让其能接收函数。给dispatch一个函数,dispatch会立即执行,且会强制它state和dispatch函数自身作为这个立即执行函数的参数!(这个立即执行函数中可以包含异步耗时的代码,相当于仓库发了ajax)
使用后,可以在仓库中发送ajax。
// index.js文件需要改变的内容
import { createStore, combineReducers, applyMiddleware } from "redux";
import thunk from 'redux-thunk';
const store = createStore(reducer, applyMiddleware(thunk));
// 子仓库发送ajax的代码
export const CategoryActions = {
assignListMain: () => async ({ dispatch, getState}) => {
// getState调用可以拿到当前仓库的state
let result = await http('/category/list/0');
dispatch({ type: ACTIONS.MAIN, payload: result });
}
}
5.下载react-redux包:
为了在根实例index.js中导入该包,就能将redux仓库和项目联系起来。
yarn add react-redux
需要从react-redux中先解构除Provider,再用Provider包裹主根组件,并在标签中导入仓库store。
// 根实例index.js
// 在使用jsx对象时,必须引入react
// 根实例,将根组件App渲染到挂载点
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';
import { HashRouter } from 'react-router-dom';
import store from './store';
import { Provider } from 'react-redux';
ReactDOM.render(
<Provider store={ store }>
<HashRouter>
<App />
</HashRouter>
</Provider>,
document.getElementById('root')
);
6.组件中使用仓库:
在随便一个页面级组件中,拿出仓库中的数据,并且通知仓库修改数据。
import React, { Component } from 'react';
import { MiNav } from '../../components';
import { connect } from 'react-redux';
import { TestActions } from '../../store';
class Home extends Component {
render() {
return (
<div>这是主页{ this.props.a }
<MiNav />
<button onClick={() => this.props.change(123123)}>
test中的a值123123
</button>
</div>
);
}
}
const mapStateToProps = (state, props) => ({
a: state.test.a
});
const mapDispatchToProps = (dispatch, props) => ({
change: value => dispatch(TestActions.changeA(value))
});
export default connect(mapStateToProps, mapDispatchToProps)(Home);
方法用react-redux包中的connect方法产生一个高阶组件,让该组件称为一个连接仓库和Home组件的中间组件。
connect中需要两个函数作为参数,两个函数的返回值将会assign合并到服务(包裹)组件的props中。
第一个参数:mapStateToProps(state,props)。主要作用是将要服务的组件中从仓库state中映射数据。该函数中有两个参数:
state为redux仓库中当前的state,props为父组件向本组件传递的值。
第二个参数:mapDispatchToProps(dispatch,props)。主要作用就是将仓库中的dispatch方法封装成函数,映射到包裹组件的props中以供使用,让包裹组件可以修改redux中的数据。
dispatch是redux中的dispatch函数。
以上就是react中实现仓库的方法。需要下载的包比较多。使用仓库时,需要预先想好仓库的结构,希望存放和修改的数据以及如何对数据进行修改。