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 defaultconnect(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, 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(,document.getElementById('root'));)复制代码