redux速成法典

819 阅读6分钟

redux速成法典

redux

(1).简介: redux指的是 JavaScript 状态容器,提供可预测化的状态管理, 是由 Flux 演变而来。 Redux 与 React 没有关系,就好像 Javascript 和 Java。

redux它本身是基于js的,可以应用在任何地方,包括原生的js。 类似于vue中vuex。

为什么需要redux?
随着 JavaScript 单页应用开发日趋复杂,JavaScript 需要管理比任何时候都要多的 state (状态)。 由于 管理不断变化的 state 非常困难。state 在什么时候,由于什么原因,如何变化已然不受控制。 Redux 试图让 state 的变化变得可预测,同时可以集中管理。
(2).三大原则
1.唯一数据源 应用的状态数据应该只存储在唯一的一个Store上,即 State 树。
2.保存状态只读 不能直接修改state的值,必须通过派发action对象完成。通过getState()获取值
3.数据改变只能通过纯函数 这里的纯函数就是reducer,函数的返回结果必须有两个参数state和action决定
(3).redux的使用

创建Store

Store即是保存数据的地方,可以把它看做一个容器。整个应用只有一个Store,从表现形式上来看,就是一个普通的对象。 在Redux应用中,所有的state都被保存在一个单一对象中。Redux 提供createStore这个函数,用来生成 Store。 当前时刻的 Stote,可以通过store.getState()拿到。
创建Store格式:
Redux.createStore(reducer,state)
//其中,reducer是必须的。

例如:

const Number={
number:8
}
 store=Reducer.createStore(reducer,Number);

几个关键方法:

getState:用于获取状态

dispatch:用于派发(触发)某个action

subscribe:订阅,一旦状态发生变化,就会执行回调函数

Action

Action表示要执行的动作,就是 View 发出的通知,表示 State 应该要发生变化了,它本质上就是一个javascript对象。 Action 描述当前发生的事情。改变 State 的唯一办法,就是触发 Action。
const AddNumber = {
  type: 'ADD_NUMBER'
};

注意,action就是一个对象,该对象必须包含一个type属性,用来描述动作的名称,其它属性可以根据需求来定义。

action creators

用于创建action对象,返回一个action对象的函数,称之为action creators。
例如:

function AddNumber(Add){
    type:"ADD_NUMBER",
    Add
}

Reducer

reducer的职责就是根据不同的action来完成state的变化。action只是描述了 有事情发生了 这一事实,但并没有指明应该应用如何更新state。
reducer是一个纯函数,接受旧的state和action,然后返回新的state 基本格式如下:

function reducer(oldState,action){
// 根据action的type,完成相应的操作
return newState
}

例如:

function reducer(state=Number,action){
    Switch(action.type){
        case "ADD_NUMBER":
        return{number:state.number+1};
        default:
        return state;
    }
}

注意:

state参数,表示旧的状态,可以赋默认值,也可以直接写。

针对return,必须要返回一个和初始状态具备相同结构的对象,不要直接修改state。

必须要写上default,并且在default的时候,就直接返回state本身。

combineReducers方法

Redux 提供了一个combineReducers方法,用于 Reducer 的拆分。你只要定义各个子 Reducer 函数,然后用这个方法,将它们合成一个大的 Reducer。 这种写法有一个前提,就是 State 的属性名必须与子 Reducer 同名。

纯函数

纯函数,就是指只要是同样的输入,必定得到同样类型的输出。

在纯函数中,这些代码是不能出现的:

和时间相关的,date对象

和执行平台相关的,dom操作,fs操作等

必须遵守以下一些约束。

不得改写参数

不能调用系统I/O的API(如DOM操作、http请求)

不能调用Date.now或者Math.random等不纯的方法

由于 Reducer 是纯函数,就可以保证同样的State,必定得到同样的 state。但也正因为这一点,Reducer 函数里面不能改变 State,必须返回一个全新的对象。

React-Redux

将React和Redux连接起来,需要使用react-redux,这是redux作者为react封装的专用库。

需要明白,这里有三个库:

React.js

Redux

React-redux

这三个库是各自独立,没有任何的包含关系。 Redux 默认并不包含react-redux,需要单独安装。

React-Redux 将所有组件分成两大类:UI 组件(presentational component)和容器组件(container component)。 UI 组件负责 UI 的呈现,容器组件负责管理数据和逻辑。 UI组件:

  • 只负责 UI 的呈现,不带有任何业务逻辑
  • 没有状态(即不使用this.state这个变量)
  • 所有数据都由参数(this.props)提供
  • 不使用任何 Redux 的 API

容器组件:

  • 负责管理数据和业务逻辑,不负责 UI 的呈现
  • 带有内部状态
  • 使用 Redux 的 API

如果一个组件既有 UI 又有业务逻辑,将它拆分成下面的结构:

外面是一个容器组件,里面包了一个UI 组件。前者负责与外部的通信,将数据传给后者,由后者渲染出视图。 React-Redux 规定,所有的 UI 组件都由用户提供,容器组件则是由 React-Redux 自动生成。也就是说,用户负责视觉层,状态管理则是全部交给它。

connect方法

react-redux提供了一个connect方法,用于从笨拙组件生成容器组件,connect的意思是将两种组件连接起来。
  • 需要搞清楚,在我们当前定义的组件中,都是展示组件。

容器组件,应该有自己的状态和逻辑。 所谓的状态,就是指state,也就说数据。所谓的逻辑,就是指修改state的方法,也就是方法。

为了生成容器组件,需要给出两方面的信息:

  • 状态,state对象如何转成笨拙组件的属性
  • 更新状态的方法,用户的操作如何变为action对象,从笨拙组件传出去

先导入connect方法:

import {connect} from 'react-redux'

调用Connect方法的格式如下:

connect(mapStateToProps,mapDispatchToProps)(展示组件)

就会返回一个容器组件

mapStateToProps函数用于建立从state对象到props对象的映射。 接受state作为参数,返回一个对象,对象中的每一个键值对都是一个映射。

mapDispatchToProps函数用于建立笨拙组件的参数到store.dispatch方法的映射。 接受dispatch作为参数。

在具体映射的时候,可以使用redux提供的 bindActionCreators 函数。 bindActionCreators(actionCreators,dispatch)

部分代码如下:

import {connect} from "rect-redux";
import {bindActionCreaters} from "redux";
function mapStateToProp(state){
    return(
        counter:state.counter
    )
}
function mapDispatchToProps(dispath){
    return bindActionCreators(actions,dispath)
}
export default
connect(mapStateToProps,mapDispatchToProps)(Counter);

这样以来,这个Counter组件就变成了一个容器组件了。

  • 注意如果你直接这样用得话,会报错如下:
Uncaught Invariant Violation:Could not find "store" in either the context or props of "Connect(Counter)". Either wrap the root component in a <Provider>, or explicitly pass "store" as a prop to "Connect(Counter)".

意思是指,无法获取store。所以你需要下面这个组件。

Provider组件

在定义mapStateToProps和mapDispatchToProps的时候,用到了store,才能dispatch。所以,需要引入store。 此时,需要使用Provider组件。
  • Provider组件的作用,就是给后代组件提供store对象。 通常需要放到入口的js文件中。使用如下:
import {Provider} from "react-redux";
import store from "./store";
ReactDOM.render(
    <Prover store={store}>
<App>
</Prover>,
document.getElementById('root'));
)