介绍 Redux
- Redux是一个数据状态管理插件,搭配 React 特别合适,详细的用法可见Redux官网
使用场景
- 无论是移动端还是 pc 端,当你使用 React 或者 vue 开发组件化的 SPA 程序时,组件之间共享信息是一个非常大的问题。
- 因此每个系统都需要一个管理多组件使用的公共信息的功能,这就是 Redux 的作用。同理,vue 也有相应的工具,即 vuex ,可以自己去 github 上搜索相关资料。
- 只要使用 React 开发系统,你绝大部分都需要结合 Redux 来使用
安装
- 如果单纯使用 Redux 仅仅安装 Redux 即可,执行npm install redux –save,不过在 React 中使用 Redux 肯定会用到 react-redux 这一工具,因此这里一起安装完,执行npm install react-redux –save。
基本使用
redux 中的入门demo
123456789101112131415161718192021222324252627282930import { createStore } from 'redux'export default function () {// 下面这一段代码,就是 https://github.com/reactjs/redux 中的入门demo// 定义计算规则,即 reducerfunction counter(state = 0, action) {switch (action.type) {case 'INCREMENT':return state + 1case 'DECREMENT':return state - 1default:return state}}// 根据计算规则生成 storelet store = createStore(counter)// 定义数据(即 state)变化之后的派发规则store.subscribe(() => {console.log('current state', store.getState())})// 触发数据变化store.dispatch({type: 'INCREMENT'})store.dispatch({type: 'INCREMENT'})store.dispatch({type: 'DECREMENT'})}Redux 是一个管理数据的工具,我们创建一个store变量用来管理数据。
- 创建store用来管理数据,具体的管理形式是什么呢?
- 第一,要通过一个函数来触发数据的变化,即dispatch,触发的时候一定要符合之前定制的规则,否则无效
- 第二,数据一旦发生变化时,会导致怎样后果,即subscribe中定义的函数会执行。
- 第三,如何取得当前的数据,即store.getState()。
- 还有一点特别要注意,即在规则函数中,数据变化时要return一个新的值,而不是直接修改原来的值。
Redux 和 React 结合使用
- 以下请参考redux-demo项目
创建 store
首先也需要创建一个store,参见/src/store/index.js的代码。创建store之前要有规则,这里的第一个参数就是这个规则
12345import {createStore} from 'redux'import rootReduer from '../reducers'const store = createStore(rootReduer, window.devToolsExtension ? window.devToolsExtension() : undefined)export default store第二个参数即初始化的数据,第三个参数可调起 chrome 扩展程序,具体可参见 redux-devtools
- 创建规则(Reducer)
- 使用 Redux 时,刚才提到的“规则”被称作reducer,因此这里的数据规则代码都在/src/reducers目录下。
- /src/constants/userinfo.js中这些 const 会在多个文件中使用,因此要抽象出来。
- /src/reducers/index.js中 用combineReducers这个函数对/src/reducers/userinfo.js的数据进行了封装,这样做是为了更好的扩展性。
- 数据结构如果复杂,必须分组管理。因此我们需要用state.userinfo来表示用户数据—这就是用combineReducers封装各个 reducer 的作用。
- 创建 action
- 上面的 demo 中,最后执行数据变化时store.dispatch({type: ‘INCREMENT’}),这里的{type: ‘INCREMENT’}是我们手动写上的,而在实际的应用中,我们需要用一些函数将它封装起来,即/src/actions中的文件,虽然此处只有userinfo.js这一个文件。
- /src/actions/userinfo.js中,我们把每个业务操作都封装为一个函数,该函数接收data,然后再根据 reducer 的规则对 data 进行封装,最后返回。当然,最后返回的结果肯定还是会交给dispatch来处理。
Redux结合到 React
创建了store并传递给
组件,然后让 组件作为所有组件的根节点 123456789101112import React from 'react'import {render} from 'react-dom'import App from './App'import {Provider} from 'react-redux'import store from './store'render(<Provider store={store}><App/></Provider>,document.getElementById('root'))然后看./src/App.js,注意下面这些代码。通过下面的封装,就把userinfo和userinfoActions当做props传入到App组件中了,即在App组件中通过this.props.userinfo和this.props.userinfoActions即可获取数据和actions
1234567function mapStateToProps(state) {return { userinfo: state.userinfo }}function mapDispatchToProps(dispatch) {return { userinfoActions: bindActionCreators(userinfoActions, dispatch) }}export default connect( mapStateToProps, mapDispatchToProps )(App)获取了数据和 actions 该怎么用呢?我们将它们传递给子组件,A和B组件负责展示数据,C组件负责触发actions。具体可参见各个组件的源代码。
12345678910111213render() {return (<div><p>hello world</p><hr/><A userinfo={this.props.userinfo}/><hr/><B userinfo={this.props.userinfo}/><hr/><C userinfoActions={this.props.userinfoActions}/></div>)}