安装
npm install redux --save
npm install react-redux --save
文件路径
src
index.js(react初始化文件)
redux(redux文件夹)
index.js(redux统一出口文件)
assistant.js(redux的模块reducer统一输出文件)
index.js(redux统一模块文件)
**.js(redux模块文件)
src/index.js 初始化文件
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import App from './App'
import * as serviceWorker from './serviceWorker'
import configureStore from './redux' // 引入redux
// React-Redux 提供<Provider/>组件,能够使你的整个app访问到Redux store中的数据:
import {Provider} from 'react-redux'
const store = configureStore()
ReactDOM.render(
<Provider store={store}>
<App/>
</Provider>,
document.getElementById('root')
)
src/redux/modules/car.js (redux模块文件)
// 初始化state数据
export const initialState = {
count: 0,
title: '首页展示'
}
// 定义action常量
const actionType = {
ADD_COUNT: 'ADD_COUNT' // 新增数量
}
// 定义action方法
export const carActions = {
addCount(count) {
return {
type: actionType.ADD_COUNT,
count
}
}
}
// 输出模块的reducer方法
export default function car(state = initialState, action = {}) {
switch (action.type) {
case actionType.ADD_COUNT:
return {...state, ...{count: state.count + action.count}}
default:
return state
}
}
src/redux/modules/index.js 把module里面除了index.js的文件都自动引入,并调用redux的combineReducers方法和所有的reducer合并且统一输出(redux统一模块文件)
import {combineReducers} from 'redux'
let moduleMethods = {}
;(function updateModules() {
const requireModule = require.context('.', true, /^((?!index|\.unit\.).)*\.js$/)
requireModule.keys().forEach((fileName) => {
const moduleConfig = requireModule(fileName)
const moduleName = (fileName.replace(/^\.\//, '').replace(/\.js/, ''))
moduleMethods[moduleName] = moduleConfig.default || moduleConfig
})
})()
// 自动引入模块中的js文件,并合并在reducer中
const reducers = combineReducers({
...moduleMethods
})
export default reducers
src/redux/index.js 注册一个store,并且订阅一个subscribe监听数据变化时进行打印,向页面中抛出一个store(redux统一出口文件)
import {createStore} from 'redux'
import reducers from './modules' // 获取所有的reducer
export default function configureStore(initialState) {
// reducers: 当前的 state 树和要处理的; action:initialState:初始时的 state
const store = createStore(reducers, initialState)
function listen() {
// 订阅打印最新的redux
console.warn('订阅打印最新的redux:', store.getState())
}
store.subscribe(listen)
if (module.hot) {
module.hot.accept('./modules', () => {
const nextReducer = require('./modules')
store.replaceReducer(nextReducer)
})
}
return store
}
src/redux/assistant.js 统一混合数据,页面中可以按需引入,使用connect连接在全局中混入方法
import {bindActionCreators} from 'redux'
import {carActions} from './modules/car' // 购物车
const actionMethods = {
carActions,
shoppingActions
}
/*********单个引入state,action*********/
export function carState(state) {
return state.car
}
export function carAction(dispatch) {
return {
...bindActionCreators(carActions, dispatch)
}
}
/**
* 一个页面使用多模块数据
* @param state
* @param value -- string/array
*value不传参时默认取所有的state合并到页面中, value可传模块字符串取单个模块的数值合并到页面数据
* value传多个参数时可以数组的形式,可把多个模块的数据合并到页面中
*/
export function mapStateToProps(state, value = '') {
let stateObj = {}
Object.keys(state).forEach((name) => {
stateObj = {...stateObj, ...state[name]}
})
switch (typeof value) {
case 'string':
stateObj = {}
stateObj = value ? state[value] : stateObj
break
case 'object':
if (Array.isArray(value)) {
stateObj = {}
value.forEach((item) => {
stateObj = {...stateObj, ...state[item]}
})
}
break
default:
break
}
return stateObj
}
/**
* 一个页面使用多模块action
* @param state
* @param value -- string/array
*value不传参时默认取所有的state合并到页面中, value可传模块字符串取单个模块的数值合并到页面数据 eg: mapDispatchToProps(dispatch, 'carActions')
* value传多个参数时可以数组的形式,可把多个模块的数据合并到页面中 eg: mapDispatchToProps(dispatch, ['carActions', 'shoppingActions'])
*/
export function mapDispatchToProps(dispatch, action = '') {
let actionObj = {}
Object.keys(actionMethods).forEach((item) => {
actionObj = {...actionObj, ...actionMethods[item]}
})
switch (typeof action) {
case 'string':
if (action) {
actionObj = {...actionMethods[action]}
}
break
case 'object':
if (Array.isArray(action)) {
actionObj = {}
action.forEach(item => {
actionObj = {...actionObj, ...actionMethods[item]}
})
}
break
default:
break
}
return {
...bindActionCreators(actionObj, dispatch)
}
}
src/app.js 页面中使用的案例
引入单模块案例
import React, {Component} from 'react';
import logo from './logo.svg';
import './App.css';
// React-Redux提供一个connect方法能够让你把组件和store连接起来。
import {connect} from 'react-redux'
import {carState, carAction} from './redux/assistant'
class App extends Component {
constructor(props) {
super(props)
this.state = {}
}
addCount(count) {
this.props.addCount(count)
}
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo"/>
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<p>当前标题为:{this.props.shopTitle}</p>
<p>当前数量为{this.props.count}</p>
<button onClick={() => this.addCount(5)}>点击增加数量</button>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
)
}
}
export default connect(carState, carAction)(App)
引入多模块案例
import React, {Component} from 'react';
import logo from './logo.svg';
import './App.css';
import {connect} from 'react-redux'
import {mapDispatchToProps, mapStateToProps} from './redux/assistant'
function getState(state) {
// 传入多个模块文件名称
return mapStateToProps(state, ['car', 'shopping'])
}
function getAction(dispatch) {
// 传入多个模块action
return mapDispatchToProps(dispatch, ['carActions', 'shoppingActions'])
}
class App extends Component {
constructor(props) {
super(props)
this.state = {}
}
addCount(count) {
this.props.addCount(count)
// this.props.setShopTitle('测试多模块redux成功')
}
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo"/>
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<p>当前标题为:{this.props.shopTitle}</p>
<p>当前数量为{this.props.count}</p>
<button onClick={() => this.addCount(5)}>点击增加数量</button>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
)
}
}
export default connect(getState, getAction)(App)
网友评论