相关文章
状态管理(Redux同步处理)
readux
众所周知,react没有办法写大型项目。(随着项目的增大,组件的增多,组件之间的传值变得愈发困难,并且代码结构也逐渐混沌。)为了解决这个问题FaceBook在2014年提出了Flux概念,2015年redux出世了。redux将Flux与函数编程结合一起,变成了最热门的前端框架。
你可能不需要Redux
不可否认的是Redux
是一个很好的框架,能够解决一些关键的问题。但redux
是非必须使用的,也就是说一般情况下,你不会使用到它。
Redux
创造者Dan Abramov
说过
“只有遇到 React 实在解决不了的问题,你才需要 Redux 。”
也就是说,一般我们不会用到他。对于项目较为简单的项目,使用Redux
会增加我们项目的负担(复杂性、维护性)。
一般什么时候会用到redux呢?
- 需要多个不同层级组件共享数据
- 多交互,多数据源
基础概念和API
原理图
redux是一个状态管理的解决方案,你可以不使用Redux。redux中有一个store
仓库,仓库存放着state的数据。仓库的唯一管理员时reducer,只有他才能操作store
仓库中的数据。首先用户点击了一个按钮,这个按钮的onclick事件函数中,要操作store中的数据。而仓库store
中的数据只有reducer仓库管理者才可以修改。那么我们只需要告诉他,应该怎么修改就好了。我们通过dispath这个行为告诉reducer应该怎么行动(Action),仓库唯一管理者reducer就会更具你的action进行仓库数据的修改。仓库更改后如果没有人告诉我们仓库数据更改了,我们时不知道的。因此这又会出现一个subscribe仓库监听者,来告诉我们仓库发生了改变。我们在根据仓库中的数据进行修改信息。
store
Store 就是保存数据的地方,你可以把它看成一个容器。整个应用只能有一个 Store。
redux
提供createStore
这个函数,用来生成 Store。
import { createStore } from 'redux'; const store = createStore(reducer);
上面代码中,createStore
函数接受另一个函数作为参数,返回新生成的 Store 对象。
State
Store
对象包含所有数据。当前时刻的 State,可以通过store.getState()
拿到。
import { createStore } from 'redux'; const store = createStore(fn); const state = store.getState();
Redux
规定, 一个 State 对应一个 View。只要 State 相同,View 就相同。你知道 State,就知道 View 是什么样,反之亦然。
Action
State 的变化,会导致 View 的变化。但是,用户接触不到 State,只能接触到 View。所以,State 的变化必须是 View 导致的。Action 就是 View 发出的通知,表示 State 应该要发生变化了。.
Action 是一个对象。其中的type
属性是必须的,表示 Action 的名称。其他属性可以自由设置,社区有一个规范可以参考。
const action = {
type: 'ADD_TODO',
payload: 'Learn Redux'
};
上面代码中,Action 的名称是ADD_TODO
,它携带的信息是字符串Learn Redux
。
可以这样理解,Action 描述当前发生的事情。改变 State 的唯一办法,就是使用 Action。它会运送数据到 Store。
import {
createStore} from 'redux'
const store = createStore()
export default store
store.dispatch
store.dispatch()
是 View 发出 Action 的唯一方法。
import { createStore } from 'redux'; const store = createStore(fn); store.dispatch({ type: 'ADD_TODO', payload: 'Learn Redux' });
上面代码中,store.dispatch
接受一个 Action 对象作为参数,将它发送出去。
Reducer
Store 收到 Action 以后,必须给出一个新的 State,这样 View 才会发生变化。这种 State 的计算过程就叫做 Reducer。
Reducer 是一个函数,它接受 Action 和当前 State 作为参数,返回一个新的 State。
const defaultState = 0;
const reducer = (state = defaultState, action) => {
switch (action.type) {
case 'ADD':
return state + action.payload;
default:
return state;
}
};
const state = reducer(1, {
type: 'ADD',
payload: 2
});
Reducer 函数最重要的特征是,它是一个纯函数。也就是说,只要是同样的输入,必定得到同样的输出。
纯函数是函数式编程的概念,必须遵守以下一些约束。
纯函数特性
- 不得改写参数
- 不能调用系统 I/O 的API
- 不能调用
Date.now()
或者Math.random()
等不纯的方法,因为每次会得到不一样的结果
由于 Reducer 是纯函数,就可以保证同样的State,必定得到同样的 View。但也正因为这一点,Reducer 函数里面不能改变 State,必须返回一个全新的对象。
// State 是一个数组
function reducer(state, action) {
return [...state, newItem];
}
store.subscribe()
Store 允许使用store.subscribe
方法设置监听函数,一旦 State 发生变化,就自动执行这个函数。
import { createStore } from 'redux'; const store = createStore(reducer); const listener = () => { this.setState(store.getState()) } store.subscribe(listener);
显然,只要把 View 的更新函数(对于 React 项目,就是组件的render
方法或setState
方法)放入listen
,就会实现 View 的自动渲染。
API
- store.getState()
- store.dispatch()
- store.subscribe()
import { createStore } from 'redux'; let { subscribe, dispatch, getState } = createStore(reducer);
createStore
方法还可以接受第二个参数,表示 State 的最初状态。这通常是服务器给出的。
let store = createStore(todoApp, window.STATE_FROM_SERVER)
上面代码中,window.STATE_FROM_SERVER
就是整个应用的状态初始值。注意,如果提供了这个参数,它会覆盖 Reducer 函数的默认初始值。
下面是createStore
方法的一个简单实现,可以了解一下 Store 是怎么生成的。
const createStore = (reducer) => { let state; let listeners = []; const getState = () => state; const dispatch = (action) => { state = reducer(state, action); listeners.forEach(listener => listener()); }; const subscribe = (listener) => { listeners.push(listener); return () => { listeners = listeners.filter(l => l !== listener); } }; dispatch({ }); return { getState, dispatch, subscribe }; };
小结
Redux
是一个状态管理工具
- reducer:仓库数据唯一操作者
- store:仓库
- Action:view操作store的唯一方式。
- dispatch:发送Action给reducer的行为。
- subscribe:对仓库的数据进行监听。
//1:注册reducer,数据操作者
const reducer = function(state={
num:0},action){
switch(action.type){
case 'add':
state.num++;
break;
case 'decrement':
state.num--;
break;
default:
break;
}
return {
...state} //这里是一个深拷贝,redux通过监听仓库的内存,来判断数据是否更新。
}
//2:创建仓库
const store = createStore(reducer)
function add(){
//5:调用仓库中的方法
store.dispatch({
type:'add'})
}
function decrement(){
//6:调用仓库中的方法
store.dispatch({
type:'decrement'})
}
//3:注册组件
const Counter = function(props){
//4:获取store中state的值
const state = store.getState()
return (
<div>
<h1>计数数量:{
state.num}</h1>
<button onClick={
add}>技术+1</button>
<button onClick={
decrement}>技术-1</button>
</div>
)
}
//7:监听数据变化,并更新对应组件。
store.subscribe(() => {
ReactDOM.render(
<React.StrictMode>
<Counter/>
<App />
</React.StrictMode>,
document.getElementById('root')
);
})