开发中配置&优化
目录
.src下建立:-redux-store.js-reducers.js-axxReducer.js-bxxReducer.js-actionTypes.js -放置容易写错的type值-actionCreators.js -专门用于创建action对象
优化
全过程基础优化配置
/****actionTypes.js 定义type值****/
//添加事件
export const TO_ADD = 'toAdd'
//删除事件
export const TO_DEL = 'toDel'
/****actionCreators.js 创建action对象****/
import { TO_ADD , TO_DEL } from 'actionTypes.js'
import store from ''
export const addFnCreatore = () =>{
let action = {
type:TO_ADD
}
store.dispatch(action)
}
/****axxReducer.js 定义触发修改state****/
import { TO_ADD , TO_DEL } from 'actionTypes.js'
switch (){
case TO_ADD:
//...
}
/****组件调用****/
import {addFnCreatore} from 'actionCreators.js'
addFnCreatore()
如果项目复杂可继续优化
/****actionCreators.js 一个函数即可, 其他通过传参****/
import store from ''
export defaul (type,value) =>{
let action = {
type,
value
}
store.dispatch(action)
}
/****组件调用****/
import { TO_ADD , TO_DEL } from 'actionTypes.js'
import creator from 'actionCreators.js'
creator(TO_ADD)
reducer复杂时 可以将case内容抽离出来
redux
原理图&简易代码

function createStore(reducer){
var list = []
var state = reducer(undefined,{})
function subscribe(callback){
list.push(callback)
}
function dispatch(action){
state = reducer(state,action)
for(var i in list){
list[i] && list[i]()
}
}
function getState(){
return state
}
return {
subscribe,
dispatch,
getState
}
}
理解
安装: npm install redux redux-thunk
(1).去除Count组件自身的状态
(2).src下建立:
-redux
-store.js
-count_reducer.js
-count_action.js 专门用于创建action对象
-constant.js 放置容易写错的type值
(3).store.js:
1).引入redux中的createStore函数,创建一个store
2).createStore调用时要传入一个为其服务的reducer
3).记得暴露store对象
(4).count_reducer.js:
1).reducer的本质是一个函数,接收:preState,action,返回加工后的状态
2).reducer有两个作用:初始化状态,加工状态
3).reducer被第一次调用时,是store自动触发的,
传递的preState是undefined,
传递的action是:{type:'@@REDUX/INIT_a.2.b.4}
(5).在index.js中监测store中状态的改变,一旦发生改变重新渲染<App/>
备注:redux只负责管理状态,至于状态的改变驱动着页面的展示,要靠我们自己写。
store.js - 暴露store对象
/*
该文件专门用于暴露一个store对象,整个应用只有一个store对象
*/
//1. 引入createStore,专门用于创建redux中最为核心的store对象
//applyMiddleware用于引入中间件 //combineReducers用于合并多个thunk
import {createStore,applyMiddleware,combineReducers} from 'redux'
//2. 引入为City组件和Tabbar服务的reducer (每个功能单独作为一个reducer)
//引入为Count组件服务的reducer
import countReducer from './count_reducer'
import countReducer2 from './count_reducer2'
//合并reducer
const reducer = combineReducers({
countReducer,
countReducer2
})
//3. 引入中间件 下列两种二选一或全选都可以
//用于支持异步action 回调函数写法
import reduxThunk from 'redux-thunk'
//用于支持异步action promise写法
import reduxPromise from 'redux-promise'
//4. 暴露store
export default createStore(reducer,applyMiddleware(reduxThunk,reduxPromise))
使用redux-tools时
//5.如果使用redux-tools需要改写为
import {applyMiddleware, combineReducers, createStore,compose} from 'redux'
import countReducer from './count_reducer'
import countReducer2 from './count_reducer2'
import reduxThunk from 'redux-thunk'
import reduxPromise from 'redux-promise'
const reducer = combineReducers({
countReducer,
countReducer2
})
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(reducer,composeEnhancers(applyMiddleware(reduxThunk,reduxPromise)));
constant.js - 定义type常量值
/*
该模块是用于定义action对象中type类型的常量值,目的只有一个:便于管理的同时防止程序员单词写错
*/
export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'
count_reducer.js - switch函数
/*
1.该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数
2.reducer函数会接到两个参数,分别为:之前的状态(preState),动作对象(action)
*/
import {INCREMENT,DECREMENT} from './constant'
const initState = 0 //初始化状态
export default function countReducer(preState=initState,action){
// console.log(preState);
//从action对象中获取:type、data
const {type,data} = action
//根据type决定如何加工数据
switch (type) {
case INCREMENT: //如果是加
return preState + data
case DECREMENT: //若果是减
return preState - data
default:
return preState
}
}
count_action.js - {type,data}
/*
该文件专门为Count组件生成action对象
*/
import {INCREMENT,DECREMENT} from './constant'
//同步action,就是指action的值为Object类型的一般对象
export const createIncrementAction = data => ({type:INCREMENT,data})
export const createDecrementAction = data => ({type:DECREMENT,data})
//异步action,就是指action的值为函数,异步action中一般都会调用同步action,异步action不是必须要用的。
//这是redux-thunk写法(函数写法) 也可以使用redux-promise写法(promise写法)
export const createIncrementAsyncAction = (data,time) => {
return (dispatch)=>{
setTimeout(()=>{
dispatch(createIncrementAction(data))
},time)
}
}
xxx组件 - subscribe监测
store.subscribe()监测store中状态的改变,一旦发生改变则获取数据再进行其他逻辑处理
import React,{useState,useEffect} from 'react'
import store from '../redux/store'
export default function Cinemas(props) {
useEffect(() => {
//订阅
var unsubscribe = store.subscribe(()=>{
console.log("cinema 中订阅",store.getState().countReducer)
//获取数据后可以将数据set为自身数据
})
return ()=>{
//取消订阅?
unsubscribe()
}
}, [])
}
Count组件 - dispatch触发
import React, { Component } from 'react'
//引入store,用于获取redux中保存状态
import store from '../../redux/store'
//引入actionCreator,专门用于创建action对象
import {
createIncrementAction,
createDecrementAction,
createIncrementAsyncAction
} from '../../redux/count_action'
export default class Count extends Component {
//加法
increment = ()=>{
const {value} = this.selectNumber
store.dispatch(createIncrementAction(value*1))
}
//减法
decrement = ()=>{
const {value} = this.selectNumber
store.dispatch(createDecrementAction(value*1))
}
//奇数再加
incrementIfOdd = ()=>{
const {value} = this.selectNumber
const count = store.getState()
if(count % 2 !== 0){
store.dispatch(createIncrementAction(value*1))
}
}
//异步加
incrementAsync = ()=>{
const {value} = this.selectNumber
// setTimeout(()=>{
store.dispatch(createIncrementAsyncAction(value*1,500))
// },500)
}
render() {
return (
<div>
<h1>当前求和为:{store.getState()}</h1>
<select ref={c => this.selectNumber = c}>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button onClick={this.increment}>+</button>
<button onClick={this.decrement}>-</button>
<button onClick={this.incrementIfOdd}>当前求和为奇数再加</button>
<button onClick={this.incrementAsync}>异步加</button>
</div>
)
}
}
redux异步action版
(1).明确:延迟的动作不想交给组件自身,想交给action
(2).何时需要异步action:想要对状态进行操作,但是具体的数据靠异步任务返回。
(3).具体编码:
1).yarn add redux-thunk,并配置在store中
2).创建action的函数不再返回一般对象,而是一个函数,该函数中写异步任务。
3).异步任务有结果后,分发一个同步的action去真正操作数据。
(4).备注:异步action不是必须要写的,完全可以自己等待异步任务的结果了再去分发同步action。
//引入createStore,专门用于创建redux中最为核心的store对象
import {createStore,applyMiddleware} from 'redux'
//引入为Count组件服务的reducer
import countReducer from './count_reducer'
//引入redux-thunk,用于支持异步action
import thunk from 'redux-thunk'
//暴露store
export default createStore(countReducer,applyMiddleware(thunk))
react-redux
原理图
整体结构
src
-containers -放置UI加容器组件
-Count
-index.jsx -cout容器组件和UI组件
-Person
-index.jsx -person容器组件和UI组件
-redux -放置redux相关文件
-actions -每个组件的action文件
-count.js
-person.js
-reducers -每个组件的reducers文件
-index.js -汇总reducers给store
-count.js
-person.js
-constant.js -放置容易写错的type值
-store.js
理解
npm install redux redux-thunk
npm install react-redux
(1).明确两个概念:
1).UI组件:不能使用任何redux的api,只负责页面的呈现、交互等。
2).容器组件:负责和redux通信,将结果交给UI组件。
(2).如何创建一个容器组件————靠react-redux 的 connect函数
connect(mapStateToProps,mapDispatchToProps)(UI组件)
-mapStateToProps:映射状态,返回值是一个对象
-mapDispatchToProps:映射操作状态的方法,返回值是一个对象
(3).备注1:容器组件中的store是靠props传进去的,而不是在容器组件中直接引入
(4).备注2:mapDispatchToProps,也可以是一个对象
App.js
给count容器组件传递storeimport store from './redux/store'render() {return (<div><Count store={store} /> </div>)}
容器组件代码
//引入Count的UI组件
import CountUI from '../../components/Count'
//引入action
import {
createIncrementAction
} from '../../redux/count_action'
//引入connect用于连接UI组件与redux
import {connect} from 'react-redux'
/*
1.mapStateToProps函数返回的是一个对象;
2.返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value
3.mapStateToProps用于传递状态
*/
function mapStateToProps(state){
return {count:state}
}
/*
1.mapDispatchToProps函数返回的是一个对象;
2.返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value
3.mapDispatchToProps用于传递操作状态的方法
*/
function mapDispatchToProps(dispatch){
return {
jia:number => dispatch(createIncrementAction(number))
}
}
//使用connect()()创建并暴露一个Count的容器组件
export default connect(mapStateToProps,mapDispatchToProps)(CountUI)
count UI 组件调用 this.props.jia(value*1)
模拟connenct方法源码
//UI组件
import React,{useEffect} from 'react'
function NotFound(props) {
useEffect(() => {
console.log(props)
}, [props])
return (
<div>
404 not found
</div>
)
}
//模拟connenct方法(高阶函数)
function kerwinconnenct(cb,obj){
//接收state
var value = cb()
//接收组件
return (MyComponent)=>{
// props 路由方法...
return (props)=>{
return <div style={{color:"red"}}>
//obj(dispatch方法)
<MyComponent {...value} {...props} {...obj}/>
</div>
}
}
}
//调用传参(高阶组件)
export default kerwinconnenct(()=>{
return {
a:1,
b:2
}
},{
aa(){},
bb(){}
})(NotFound)
react-redux优化
(1).容器组件和UI组件整合一个文件
(2).无需自己给容器组件传递store,给<App/>包裹一个<Provider store={store}>即可。
(3).使用了react-redux后也不用再自己检测redux中状态的改变了,容器组件可以自动完成这个工作。
(4).mapDispatchToProps也可以简单的写成一个对象
(5).一个组件要和redux“打交道”要经过哪几步?
(1).定义好UI组件---不暴露
(2).引入connect生成一个容器组件,并暴露,写法如下:
connect(
state => ({key:value}), //映射状态
{key:xxxxxAction} //映射操作状态的方法
)(UI组件)
(4).在UI组件中通过this.props.xxxxxxx读取和操作状态
容器组件融合UI组件代码
import React, { Component } from 'react'
//引入action
import {
createIncrementAction
} from '../../redux/count_action'
//引入connect用于连接UI组件与redux
import {connect} from 'react-redux'
//定义UI组件
class Count extends Component {
//加法
increment = ()=>{
const {value} = this.selectNumber
this.props.jia(value*1)
}
render() {
//console.log('UI组件接收到的props是',this.props);
return (
<div>
<h1>当前求和为:{this.props.count}</h1>
<select ref={c => this.selectNumber = c}>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button onClick={this.increment}>+</button>
</div>
)
}
}
//使用connect()()创建并暴露一个Count的容器组件
export default connect(
state => ({count:state}),
//mapDispatchToProps的简写
{
jia:createIncrementAction
}
)(Count)
App.js
由Provider统一传递storerender() {return (<div><Count ~~store={store}~~ /> </div>)}
index.js
import store from './redux/store'
import {Provider} from 'react-redux'
ReactDOM.render(
<Provider store={store}>
<App/>
</Provider>,
document.getElementById('root')
)
redux持久化 (localStorage)
安装: npm install redux-persist
//store.js
...
import {persistStore, persistReducer} from 'redux-persist';
import storage from 'redux-persist/lib/storage';
//未知import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';
const persistConfig = {
key: 'kerwin',
storage: storage,
whitelist: ['CityReducer'], //指定白名单(需要持久化的reduce) 不指定则默认所有
//localStorage: import storage from 'redux-persist/lib/storage'
//sessionStorage: import storageSession from 'redux-persist/lib/storage/session'
//stateReconciler: autoMergeLevel2 //控制在本地存储中,新老状态怎么合并,覆盖?或者合并?
};
//改造reducer
const persistedReducer = persistReducer(persistConfig, reducer)
//改造store
const store = createStore(persistedReducer,...);
const persistor = persistStore(store)
//导出
export {store,persistor}
//改造根组件 index.js
import {persistor} from './Store'
import {PersistGate} from 'redux-persist/lib/integration/react';
<PersistGate loading={null} persistor={persistor}>
...
</PersistGate>
求和案例_react-redux数据共享版
(1).定义一个Pserson组件,和Count组件通过redux共享数据。
(2).为Person组件编写:reducer、action,配置constant常量。
(3).重点:Person的reducer和Count的Reducer要使用combineReducers进行合并,
合并后的总状态是一个对象!!!
(4).交给store的是总reducer,最后注意在组件中取出状态的时候,记得“取到位”。
Person 的redux相关文件
Person和Count 组件数据共享
求和案例_react-redux最终版
(1).所有变量名字要规范,尽量触发对象的简写形式。
(2).reducers文件夹中,编写index.js专门用于汇总并暴露所有的reducer
reducers/index.js
import {combineReducers} from 'redux'
//引入为Count组件服务的reducer
import count from './count';
import persons from'./person';
export default combineReducers({
count,
persons
});
store.js 引入reducers
//引入createStore,专门用于创建redux中最为核心的store对象
import {createStore,applyMiddleware} from 'redux'
//引入为Count组件服务的reducer
import reducer from './reducers'
//引入redux-thunk,用于支持异步action
import thunk from 'redux-thunk';
//暴露store
export default createStore(reducer,applyMiddleware(thunk))
求和案例_react-redux开发者工具的使用
(1).npm install redux-devtools-extension
(2).store中进行配置
import {composeWithDevTools} from 'redux-devtools-extension'
const store = createStore(allReducer,composeWithDevTools(applyMiddleware(thunk)))
store.js
//引入createStore,专门用于创建redux中最为核心的store对象
import {createStore,applyMiddleware} from 'redux'
//引入为Count组件服务的reducer
import reducer from './reducers'
//引入redux-thunk,用于支持异步action
import thunk from 'redux-thunk';
import {composeWithDevTools} from 'redux-devtools-extension'
//暴露store
export default createStore(reducer,composeWithDevTools(applyMiddleware(thunk)))
redux持久化
npm install redux-persist
集体看GitHub 以下是基本配置
store.js 这里将CollApsedReducer持久化
import {legacy_createStore as createStore,combineReducers} from 'redux'
import {CollApsedReducer} from './reducers/CollapsedReducer'
import {LoadingReducer} from './reducers/LoadingReducer'
//1.持久化redux
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage' // defaults to localStorage for web
//2.存入storage的规则
const persistConfig = {
key: 'loading',
storage,
blacklist: ['LoadingReducer'] //黑名单
}
const reducer = combineReducers({
CollApsedReducer,
LoadingReducer
})
//3.
const persistedReducer = persistReducer(persistConfig, reducer)
//4.
const store = createStore(persistedReducer,window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())
//5.
const persistor = persistStore(store)
//6.
export {
store,
persistor
}
app.js
import {Provider } from 'react-redux'
import IndexRouter from './router/IndexRouter'
import { store,persistor } from './redux/store'
import { PersistGate } from 'redux-persist/integration/react'
function App(){
return <Provider store = {store}>
//***
<PersistGate loading={null} persistor={persistor}>
<IndexRouter></IndexRouter>
</PersistGate>
</Provider>
}
export default App

