redux 原理
1、Redux 是什么,如何用?
Redux 是 JavaScript 状态容器,提供可预测化的状态管理。Redux 除了和 React 一起用外,还支持其它界面库。它体积很小,只有 2kb ,包括依赖。
2、为什么需要 redux?
- 1.跨组件实现 state 共享,尤其是兄弟组件之间,不使用 redux 需要在父组件中写一个状态,让兄弟组件共享这个状态
- 2.某个状态需要在任何地方都可以拿到
- 3.一个组件需要改变全局状态
- 4.一个组件需要改变另一个组件的状态
3、Redux 中的概念
-
1.store: 是一个容器/仓库,存放整个应用的state,包含应用中需要统一管理的状态及操作状态相关的动作。每个组件都能读取store中的任何一个state,通过 createStore 方法创建 store 实例
- store 就是 redux 的一个数据中心,简单的理解就是我们所有的数据都会存放在里面,然后在界面上使用时,从中取出对应的数据。因此最开始,我们要创建一个这样的 store,redux提供了createStore方法。
- Store 有以下职责:
1.createStore 可以帮助我们创建一个store
2.store.dispatch 帮助我们派发 action 这个 action 会传递给 store
3.store.getState 获取到 store 里面所有的数据内容
4.store.subscribe 可以让我们订阅(监听) store 的改变,只要 store 发生改变, 这个方法的回调函数就会执行
-
2.state:状态,是全局范围内需要共享管理的组件间数据。
-
3.action:用来描述发生了什么,它是一个 JavaScript 对象,通常有两个属性:type、payload。type 指的是动作类型(比如添加、修改、删除),payload 是有效载荷(比如待添加的新待办事项对象、待修改的id、待删除的id)。
-
4.reducer: 纯函数,是实现状态更新的函数(同步状态更新),把 action 和 state 串起来(在 reducer() 函数中需要传递 state 与 action 参数),在函数主体中实现状态更新的动作,但不是直接在原始 state 上直接修改更新,而是返回更新后新的 state 对象。我们不能直接调用到 reducer() 函数,而是需要 dispatch action 触发它的调用。
dispatch 函数:用于触发 reducer() 的调用以实现更新 state 的动作。在调用 dispatch() 函数时,传递 action 作为参数。 -
注:为什么 Redux 中的 reducer 和 vuex 中的 mutation 都是同步的状态更新?
- 就是为了在开发工具里面好跟踪状态变化,因而把它设计为同步的
- vuex和redux都是一种状态管理机制。然后他们会有自己的state(状态)和修改state的方法,修改state的方法涉及到同步和异步,vuex的处理方式是同步在mutation里面,异步在actions里面,然后redux的同步就是reducer,异步更多的是用户自己去通过中间件的方式去实现
4、Redux 使用的三大原则:
- 1.单一数据源
整个应用的 state 被储存在一棵 object tree (对象树)中,并且这个 object tree 只存在于唯一一个 store 中。 - 2.State 是只读的
唯一改变 state 的方法就是触发(dispatch) action,action 是一个用于描述已发生事件的普通对象。 - 3.使用 reducer 纯函数来执行修改
为了描述 action 如何改变 state tree (状态树),需要编写 reducers。
5、绑定库 react-redux
Redux 与 React 没有任何的关系,redux 可用于其它库或框架中实现状态管理,甚至原生 js 中都能直接使用 redux 实现状态管理,只是 redux 结合 react 使用体验最好。
react 中要使用 redux 来实现状态管理,需要安装 react-redux 绑定库。
$ npm i react-redux
# 或
$ yarn add react-redux
Provider:组件,用于保存 store,以便所有 <Provider>
后代组件可以连接使用 store
connect(mapStateToProps, mapDispatchToProps):用于连接视图组件和 store
-
mapStateToProps :这个函数接收的参数必须是一个Function,作用是把 state 绑定到 props 上
- 传递 state 参数,返回一个对象,用于将 store 中 state 对象中的数据连接到组件中,并合并到组件的 props 中,以便组件使用
- 如果定义了 mapStateToProps 参数,组件将会监听 Redux store 的变化。任何时候,只要 Redux store 发生改变,mapStateToProps 函数就会被调用。从而更新组件的 state ,state 更新,props 就会更新,从而使整个页面进行更新。
-
mapDispatchToProps :这个函数接收的参数可以是一个Function,也可以是Object,它的作用是将 action creator 函数合并到组件的 props 中。
- 如果传递的是一个对象,那么每个定义在该对象的函数都将被当作Redux action creator,而且这个对象会与 Reduxstore 绑定在一起,其中所定义的方法名将作为属性名,合并到组件的 props 中;
- 如果传递的是一个函数,该函数将接收一个 dispatch 函数,然后由你来决定如何返回一个对象,这个对象通过 dispatch 函数与 action creator 以某种方式绑定在一起
-
connect() 返回的是高阶组件(高阶函数)
6、Redux工作流程:
1.视图组件在 redux 中派发 action 方法
2.action 通过 store 的 dispatch 方法派发给 store
3.store 接收 action,连同之前的 state,一起传递给 reducer ,reducer 实现更新 state 的动作后返回新的 state 给 store
4.store 去改变自己的 state
5.视图组件连接了 store ,store 中的 state 更改后,视图组件的数据也就随之更改从而重新渲染页面。
上图展示了redux数据的基本流程,简单的说就是view dispatch一个action后,通过对应reducer处理,然后更新store,最终views根据store数据的改变重新渲染界面。
7、redux 使用案例一
- 注:这个案例参考 shopping-cart 项目文件,且这个案例使用的是同步 action
- 1.action:它是用来描述行为的,即描述要进行怎样的操作,比如增删改查,为每一个行为定义一个唯一的 type 值 — 可把这个给行为定义 type 属性的操作单独提取为一个文件,比如 action-type.js
// 添加购物车项
export const ADD_CART_ITEM = Symbol('ADD_CART_ITEM')
// 移除购物车项
export const REMOVE_CART_ITEM =