Redux
JavaScript提供的一个可预测性(给一个固定的输入 必定等到一个结果)的状态容器
集中地管理react中多个组件的状态
redux是一个专门的状态管理库 (在vue中也可以使用 但是在react中会比较多)
需求场景:
1、某个组建的状态需要共享的时候
2、一个组件需要改变另一个组件状态的时候
3、组件中的状态需要在任何地方都可以拿到
三大原则:
1、单一数据源 整个react中的状态都会被统一管理到store
2、state是只读的 我们不能直接改变state 而是要通过触发redux中特定的方法进行修改
3、使用纯函数来执行修改操作:action来改变redux中的state
构建store
在src目录下建立store文件夹包含
Store.js
Reducer.js
Action.js
import {createStore} from "redux" ;import reducer from "./reducer" export const store = createStore(reducer,window .__REDUX_DEVTOOLS_EXTENSION && window .__REDUX_DEVTOOLS_EXTENSION__)
使用多个中间件(compose强函数)
import {createStore , applyMiddleware , compose} from "redux" ;import reducer from "./reducer" import thunk from "redux-thunk" ;const composeEnhancers=window .__REDUX_DEVTOOLS_EXTENSION_COMPOSE__? window .__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}):compose const enhancer=composeEnhancers(applyMiddleware(thunk))export const store = createStore(reducer, enhancer);
Reducer.js
import {CHANGE_INPUT , ADD_EVENT , SUB_EVENT } from './action' let obj={ inputValue:'Write Something' , List:[ '早上学习Node' , '下午健身' , '晚上开发项目' ] } export default (state=obj,action)=>{ switch (action.type){ case CHANGE_INPUT:{ let newState=JSON .parse(JSON .stringify(state)) newState.inputValue=action.value return newState } case ADD_EVENT:{ let newState=JSON .parse(JSON .stringify(state)) newState.List.push(action.value) newState.inputValue='Write Something' return newState } case SUB_EVENT:{ let newState=JSON .parse(JSON .stringify(state)) newState.List.splice(action.value,1 ) return newState } default :return state } }
Action.js
引入store
export各方法名称(容易找bug)
export方法(用于操作store里的变量)触发函数
import {store} from "../redux/store" ;export const CHANGE_INPUT='changeInput' export const ADD_EVENT='addEvent' export const SUB_EVENT='subEvent' export function getAction (_type,_value ) { const action={ type:_type, value:_value } store.dispatch(action) }
使用redux的组件
引入store
引入各方法名(容易找bug)
引入构建action并触发的函数
组件方法提前绑定this
将store的值放入state对应位置,如果只有store的值则直接赋值给store
store订阅并绑定方法重新设置state
import React, {Component} from 'react' ;import {Input, Button, List} from "antd" ;import {store} from "../redux/store" ;import {CHANGE_INPUT , ADD_EVENT , SUB_EVENT , getAction} from '../redux/action' class Redux1 extends Component { constructor (props ) { super (props); this .state = store.getState(); this .changeInputValue = this .changeInputValue.bind(this ) this .storeChange=this .storeChange.bind(this ) store.subscribe(this .storeChange) this .addEvent=this .addEvent.bind(this ) this .subEvent=this .subEvent.bind(this ) } render ( ) { return ( <div> <h1>Redux</h1> <div style={{margin : '10px' }}> <Input placeholder={this .state.inputValue} style={{width : '250px' }} onChange={this .changeInputValue} value={this .state.inputValue} /> <Button type='primary' style={{margin : '0 0 0 10px' }} onClick={this .addEvent}>增加 </Button> </div> <div style={{margin : '10px' , width : '300px' }}> <List bordered dataSource={this .state.List} renderItem={(item,index ) => ( <List.Item onClick={this .subEvent.bind(this ,index)}> {item} </List.Item>)} /> </div> </div> ); } changeInputValue (e ) { getAction(CHANGE_INPUT,e.target.value) } addEvent ( ) { getAction(ADD_EVENT,this .state.inputValue) } subEvent (index ) { getAction(SUB_EVENT,index) } storeChange ( ) { this .setState(store.getState()) } } export default Redux1;
React-redux
除了以下内容其他和普通Redux一样
index.js(入口)
引入Provider并包裹要使用store的组件
引入store并在Provider标签的store属性中传入(提供store的值)
import React from 'react' ;import ReactDOM from 'react-dom' ;import './index.css' ;import App from './App' ;import * as serviceWorker from './serviceWorker' ;import {BrowserRouter} from 'react-router-dom' ;import 'antd/dist/antd.css' import {Provider} from 'react-redux' import {store} from './redux/store' ReactDOM.render( <React.StrictMode> <BrowserRouter> <Provider store={store}> <App/> </Provider> </BrowserRouter> </React.StrictMode>, document .getElementById('root' ) ); serviceWorker.unregister();
使用react-redux的组件
引入connect
引入方法名
底部export的不是原本的组件而是通过connect链接store后的组件
将store的值映射到props中(connect第一个参数)
将操作store的方法映射到props中(connect第二个参数)
import React, {Component} from 'react' ;import {Button, Input, List} from "antd" ;import {connect} from 'react-redux' import {CHANGE_INPUT , ADD_EVENT , SUB_EVENT , getAction} from '../redux/action' class ReactRedux extends Component { constructor (props ) { super (props); } render ( ) { return ( <div> <h1>react-redux</h1> <div style={{margin : '10px' }}> <Input style={{width : '250px' }} value={this .props.inputValue} onChange={this .props.inputChange} /> <Button type='primary' style={{margin : '0 0 0 10px' }} onClick={this .props.addEvent.bind(this )}>增加</Button> </div> <div style={{margin : '10px' , width : '300px' }}> <List bordered dataSource={this .props.List} renderItem={(item,index ) => ( <List.Item onClick={this .props.subEvent.bind(this ,index)}> {item} </List.Item>)} /> </div> </div> ); } } const storeToProps=(store )=> { return { inputValue:store.inputValue, List:store.List } } const dispatchToProps=(dispatch )=> { return { inputChange (e ) { getAction(CHANGE_INPUT,e.target.value) }, addEvent ( ) { getAction(ADD_EVENT,this .props.inputValue) }, subEvent (index ) { getAction(SUB_EVENT,index) } } } export default connect(storeToProps,dispatchToProps)(ReactRedux);
掘金:前端LeBron
知乎:前端LeBron
持续分享技术博文,关注微信公众号👇🏻