文章目录
1、为什么要用 redux
在 React中,数据在组件中是单向流动的,数据从一个方向父组件流向子组件通过 props,所以任意两个非父子关系的组件之间通信就相对麻烦,redux的岀现就是为了方便任意组件之间相互通讯
。
2、Redux设计理念
- 将整个应用状态存储到store中,store里面保存着一个状态树 store tree;
- 组件可以派发( dispatch)行为( action)去修改state,然后为这些actions编写reducers来修改state。整个
state 转化是在 reducers 中完成
; - state发生变化,然后通知订阅该state的组件,去更新自己的视图。
3、Redux遵循的三个原则
-
单一事实来源:
整个应用的 state都被存储到一个状态树里面,并且这个状态树只存在于唯一的 store中 -
状态是只读的
:state是只读的,唯一改变 state的方法就是触发 action。 -
状态改变只能通过纯函数来执行
:为了实现根据 action 修改 state值,我们就需要编写 Reducer。它是一个纯函数,接收先前的 state 和 action 返回新的 state 。纯函数是那些返回值仅取决于其参数值的函数。
4、Redux的重要构成
-
Action
– 这是一个用来描述发生了什么事情的对象。const add =()=>{ return { type:"add", data:id, } }
上边函数返回的就是一个 Action,它是一个包含 type 和 data 的对象
。
Action 的作用就是告诉状态管理器需要做什么样的操作,
正如上边的例子,就是要添加一条信息,这样就定义了一个Action,而 data 就是你做这个操作需要的数据。 -
Reducer
– 这是一个确定状态将如何变化,以及更新状态的地方。Reducer 是一个纯函数,接受 旧 state 和 action,根据不同的 Action 做出不同的操作,并返回新的 state 。即:(state, action) => state
const reducer = (state,action)=>{ switch(action.type){ case "add": state['newItemId'] = action.data; return { ...state}; case "delete": delete state.newItemId; return { ...state}; default : return state; } }
-
Store
– 整个程序的状态state保存在Store中。import { createStore } from 'redux'; const store = createStore(reducer);
这就是 store, 用来管理 state 的单一对象,其中有三个方法:
1、store.getState()
: 获取state ,如上,经过 reducer 返回了一个新的 state,可以用该函数获取。
2、store.dispatch(action)
:发出 action,用于触发 reducer,更新 state,
3、store.subscribe(listener)
:监听变化,当 state 发生变化时,就可以在这个函数的回调中监听。
5、Redux优/缺点
5.1、优点
-
结果的可预测性
– 由于总是存在一个真实来源,即 store ,因此不存在如何将当前状态与动作和应用的其他部分同步的问题。 -
可维护性
– 代码变得更容易维护,具有可预测的结果和严格的结构。 -
服务器端渲染
– 你只需将服务器上创建的 store 传到客户端即可。这对初始渲染非常有用,并且可以优化应用性能,从而提供更好的用户体验。 -
开发人员工具
– 从操作到状态更改,开发人员可以实时跟踪应用中发生的所有事情。 -
社区和生态系统
– Redux 背后有一个巨大的社区,这使得它更加迷人。 -
易于测试
– Redux 的代码主要是小巧、纯粹和独立的功能。这使代码可测试且独立。
5.2、缺点
- 一个组件所需要的数据,必须由父组件传过来,而不能像 flux 中直接从 store 取。
- 当一个组件相关数据更新时,即使父组件不需要用到这个组件,父组件还是会重新 render,可能会有效率影响,或者需要写复杂的 shouldComponentUpdate 进行判断。
6、redux中如何进行异步操作
异步请求,我们可以在 componentDidMount中直接进行请求,无须借助 redux。
在redux中,我们可以借助异步中间件来进行异步处理。
当下主流的异步中间件只有两种 redux- thunk
、redux-saga
6.1、React中间件位置
中间件是在 action----> middlewares--->reducer
,即是在action与reducer中间。
6.2、React中间件的工作原理与流程
中间件的本质,就是对dispatch方法的一个封装,或者说是dispatch方法的一个升级
。
最原始的dispatch方法,他接收到一个对象
之后,会把这个对象传递给store,这就是view中间件的一个情况。
当我们对dispath做了一个升级之后,比如说我们使用了redux-thunk这个中间件,对dispath做了一个升级,这个时候当你调用dispatch方法,给dispatch传递的参数是一个对象的话
,那么这个dispatch就会把这个对象直接传给store,和原始的dispatch方法一样。但是如果给dispatch传递的参数是一个函数
的话,这个时候dispatch方法已经升级了。他就不会把这个函数直接传递给store。,具体流程如下:
- 先执行这个函数,
- 执行完成之后,再去调用store
所以dispatch做了一个事情,他会根据参数的不同,执行不同的事情,如果你参数是对象,那我直接传给store。如果你参数是函数,那就把这个函数执行结束。
原文链接:https://blog.csdn.net/p445098355/article/details/105218217
6.3、redux-thunk中间件的使用方法
参考地址:https://blog.csdn.net/yiyueqinghui/article/details/121415586
6.4、常用的中间件
redux- thunk
处理异步操作
使用redux-thunk中间件,改造store.dispatch,使得后者可以接受函数作为参数。redux-saga
处理异步操Redux-promise
返回一个Promise对象redux-log
打印日志
7、connect
7.1、connect的功能
连接 React 组件与 Redux Store
7.2、语法说明
connect( mapStateToProps , mapDispatchToProps , mergeProps , options )()
-
mapStateToProps
该参数为一个函数(如下)function mapStateToProps (state,[ownProps]){ ...}
定义该参数后,组件就可以监听 Redux Store 的变化,任何时候只要store发生变化,该函数就会被调用;
该函数必须返回一个纯对象,它会与组件的 props 结合,而第二个参数 ownProps 被指定时,它代表传递到该组件的props,且只要组件收到新的 props ,mapStateToProps 就被调用。 -
mapDispatchToProps
通常我们会将该参数省略,默认情况下,dispatch 函数会被注入到组件的props中,在你需要出发 action 的地方,使用该disaptch 函数将 action 发出。
7.3、示例
案例说明----- connect的整个执行流程:
在上边例子中,我们只要点击下添加链接,组件就会通过点击事件触发 dispath 函数,发送 action 到 store 中的 reducer,reducer 则根据 action 的 type 来决定执行什么操作,之后在 store 中新增一条记录(newItemId)后,返回一个新的 state (里边包含Store中发生改变后的所有值),由于组件使用 connect 将自己与 Store 绑定起来,Store 中的值发生变化就会执行 mapStateToProps方法,将新的 state 放入组件的 props,从而引发组件的渲染。
8、Redux源码
let createStore = (reducer) => {
let state;
//获取状态对象
//存放所有的监听函数
let listeners = [];
let getState = () => state;
//提供一个方法供外部调用派发action
let dispath = (action) => {
//调用管理员reducer得到新的state
state = reducer(state, action);
//执行所有的监听函数
listeners.forEach((l) => l());
}
//订阅状态变化事件,当状态改变发生之后,执行监听函数
let subscribe = (listener) => {
listeners.push(listener);
}
dispath();
return {
getState,
dispatch,
subscribe
}
}
let combineReducers = (reducers) => {
//传入一个reducers管理组,返回的是一个reducer
return function (state={
},action={
}) {
let newState = {
};
for(var attr in reducers){
newState[attr] = reducers[attr](state[attr], action);
}
return newState;
}
}