首先先说下我用redux,需要安装的东西。
1. npm i redux -S
2. npm i react-redux -S
3. npm i redux-promise -S //实现异步 配合payload 解决action同步(插件)
4. npm i redux-thunk -S //中间件
Redux store 仅支持同步数据流。使用 thunk 等中间件可以帮助在 Redux 应用中实现异步性。
可以将 thunk 看做 store 的 dispatch() 方法的封装器;我们可以使用 thunk action creator 派遣函数或 Promise,
而不是返回 action 对象。
5.cnpm i redux-persist -S 数据持久化
直接一步把5个全安装了:
npm i redux react-redux redux-promise redux-thunk redux-persist -S
在src下面建立三个文件夹,分别是 actions reducer store , 我后面的页面是home, 所以我在actions 和reducer里,分别建立了一个home.js
然后我顺便也多了3个, 一个是constants,里面建立了一个actionTypes.js(把公共的名字抽取了出来), reducer里建立了一个index.js 在那里统一引入reducer,然后抛出去,在store里注入。
reducer home.js 写入
const defaultState = { name: 'home', } export default function home (state = defaultState, action) { return state }
reducer index.js写入
import home from '@/reducer/home' export { home, }
store index.js写入
import { createStore, //创建 store compose, //配合谷歌浏览器Redux DevTools 2.17.0 使用的 combineReducers, // 把多个reduce 合并一个reduce applyMiddleware, // 加载中间件的 } from 'redux' import promise from 'redux-promise'; //实现异步。配合payload 解决action同步 import thunk from 'redux-thunk' // 数据持久化 import { persistReducer } from 'redux-persist' // 合并 reduce import storage from 'redux-persist/lib/storage' // 创建 store import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2' // 多层对象 做数据持久化 import { home } from '@/reducer' //所有reducer放一个公共地方 // 我要对哪些 reduce 的 state 做数据持久化 const rootPersistConfig = { key: 'reduxData', storage, stateReconciler: autoMergeLevel2, // 白名单 [reducer 目录内的 reduce 文件名] whitelist: ['home0429'], } const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose //配合谷歌浏览器Redux DevTools使用的 // 抽离出一个需要持久化的公共 reduce const myPersistReducer = persistReducer( rootPersistConfig, combineReducers({ home, }) ) const store = createStore( myPersistReducer, composeEnhancers(applyMiddleware(thunk, promise)) ) export { store } /** * redux 状态管理工具 管理一些变量 * store 一个项目只会有一个store * redux数据流:view用户界面(onClick)操作 => action(动作) => reduce (修改state) * redux 三大原则 */
根目录的index.js写入 这里的话,我是把路由简单配了下, 我建立了一个router文件。 里面建立了一个index,js
import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux' //Provider是容器组件,主要作用是接收Store import { persistStore } from 'redux-persist' //redux 数据持久化 import { PersistGate } from 'redux-persist/lib/integration/react'; //redux 数据持久化 import { store } from './store' import Router from './router'; //简单配置路由 ReactDOM.render( <Provider store={store}> <PersistGate loading={null} persistor={persistStore(store)}> <Router /> </PersistGate> </Provider>, document.getElementById('root') )
router index.js代码如下, 然后我把需要加载的页面 放在了assembly文件里。 在这里统一引入
import React, { Component } from 'react'; import { BrowserRouter, Switch, Route } from "react-router-dom"; import { Home } from './assembly'; //把需要加载的页面放一个公共地方 import '@/index.less'; export default class Router extends Component { render() { return ( <BrowserRouter> <Switch> <Route path='/' component={Home}/> </Switch> </BrowserRouter> ) } }
下面我写了个简单的例子。 reducer里 定义了一个name名字, 在home页面引入, 然后再定义了一个方法,来修改reducer state 的值
home 页面写入
import React from 'react' import { connect } from 'react-redux'; import { editName } from '@/actions/home' export default @connect( state => { return{ name: state.home.name //获取值 } },{ editName //actions里写入的方法 }) class Home extends React.Component { edit = () => { this.props.editName(666) //修改值 } render() { return( <div className='page-home'> <button onClick={this.edit}>点击我修改name值</button> {this.props.name} //获取值 </div> ) } }
actions home.js写入
import { HOME_EDIT_NAME } from '@/constants/actionTypes'; const editName = option => { return{ type: HOME_EDIT_NAME, //都是大写 payload: option //必须是payload名字 } } export { editName, }
reducer home.js写入
import { HOME_EDIT_NAME } from '@/constants/actionTypes'; const defaultState = { name: 'home', } export default function home (state = defaultState, action) { switch (action.type) { case HOME_EDIT_NAME: // 必须返回一个对象 return { ...state, //使用扩展运算符, 合并对象 name: action.payload } default: return state } }