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
持续分享技术博文,关注微信公众号 👇🏻