sunnychuai / blog

笔记
0 stars 0 forks source link

Mobx VS Redux #3

Open sunnychuai opened 4 years ago

sunnychuai commented 4 years ago

Redux 的设计思想

unsubscribe();

下面是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 }; };

## State
Store对象包含所有数据。如果想得到某个时点的数据,就要对 Store 生成快照。这种时点的数据集合,就叫做 State。
当前时刻的 State,可以通过store.getState()拿到。
## Action
State 的变化,会导致 View 的变化。但是,用户接触不到 State,只能接触到 View。所以,State 的变化必须是 View 导致的。Action 就是 View 发出的通知,表示 State 应该要发生变化了。
Action 是一个对象。其中的type属性是必须的,表示 Action 的名称。

const action = { type: 'ADD_TODO', payload: 'Learn Redux' };

可以这样理解,Action 描述当前发生的事情。改变 State 的唯一办法,就是使用 Action。它会运送数据到 Store。
## Reducer
定义应用状态如何响应不同动作(action),如何更新状态。
Store 收到 Action 以后,必须给出一个新的 State,这样 View 才会发生变化。这种 State 的计算过程就叫做 Reducer。

Reducer 是一个函数,它接受 Action 和当前 State 作为参数,返回一个新的 State。

const reducer = function (state, action) { // ... return new_state; };

- 纯函数
Reducer 函数最重要的特征是,它是一个纯函数。也就是说,只要是同样的输入,必定得到同样的输出。

纯函数是函数式编程的概念,必须遵守以下一些约束。

不得改写参数
不能调用系统 I/O 的API
不能调用Date.now()或者Math.random()等不纯的方法,因为每次会得到不一样的结果
由于 Reducer 是纯函数,就可以保证同样的State,必定得到同样的 View。但也正因为这一点,Reducer 函数里面不能改变 State,必须返回一个全新的对象。

// State 是一个对象 function reducer(state, action) { return Object.assign({}, state, { thingToChange }); // 或者 return { ...state, ...newState }; }

// State 是一个数组 function reducer(state, action) { return [...state, newItem]; }


最好把 State 对象设成只读。你没法改变它,要得到新的 State,唯一办法就是生成一个新对象。这样的好处是,任何时候,与某个 View 对应的 State 总是一个不变的对象。
## 工作流程
![image](https://user-images.githubusercontent.com/13477209/68921035-49166900-07b2-11ea-9c6d-5049644a9049.png)
1、首先,用户发出 Action。`store.dispatch(action);`
2、Store 自动调用 Reducer,并且传入两个参数:当前 State 和收到的 Action。 Reducer 会返回新的 State 。
3、State 一旦有变化,Store 就会调用监听函数。`store.subscribe(listener);`
4、listener可以通过store.getState()得到当前状态。如果使用的是 React,这时可以触发重新渲染 View。

# Mobx
![image](https://user-images.githubusercontent.com/13477209/68921439-b70f6000-07b3-11ea-9e19-673cd4e9f94b.png)
- State:驱动应用的数据
- Derivations:任何 源自状态并且不会再有任何进一步的相互作用的东西就是衍生。
 衍生以多种形式存在:
- 用户界面
- 衍生数据,比如剩下的待办事项的数量。
- 后端集成,比如把变化发送到服务器端。
MobX 区分了两种类型的衍生:
- Computed values(计算值) - 它们是永远可以使用纯函数(pure function)从当前可观察状态中衍生出的值。
- Reactions(反应) - Reactions 是当状态改变时需要自动发生的副作用。需要有一个桥梁来连接命令式编程(imperative programming)和响应式编程(reactive programming)。或者说得更明确一些,它们最终都需要实现I / O 操作。
 黄金法则: 如果你想创建一个基于当前状态的值时,请使用 computed。
- Actions:定义改变状态的动作函数,包括如何变更状态。
# Redux VS Mobx
## 函数式和面向对象
Redux遵循函数式编程(Functional Programming, FP)思想,如reducer就是一个纯函数,纯函数,接受输入,然后输出结果,除此之外不会有任何影响,也包括不会影响接收的参数;对于相同的输入总是输出相同的结果。
Mobx设计更多偏向于面向对象编程(OOP)和响应式编程(Reactive Programming),通常将状态包装成可观察对象,于是我们就可以使用可观察对象的所有能力,一旦状态对象变更,就能自动获得更新。
## 单一store和多store
store是应用管理数据的地方。
在Redux应用中,我们总是将所有共享的应用数据集中在一个大的store中。
而Mobx则通常按模块将应用状态划分,在多个独立的store中管理。
## JavaScript对象和可观察对象
Redux默认以JavaScript原生对象形式存储数据,
Mobx使用可观察对象:
- Redux需要手动追踪所有状态对象的变更;
- Mobx中可以监听可观察对象,当其变更时将自动触发监听;
## 不可变(Immutable)和可变(Mutable)
Redux状态对象通常是不可变的(Immutable),我们不能直接操作状态对象,而总是在原来状态对象基础上返回一个新的状态对象,这样就能很方便的返回应用上一状态;
而Mobx中可以直接使用新值更新状态对象。
# Mobx-react VS React-redux
使用Redux和React应用连接时,需要使用react-redux提供的Provider和connect:

- Provider:负责将Store注入React应用;
- connect:负责将store state注入容器组件,并选择特定状态作为容器组件props传递;

Mobx而言,同样需要两个步骤:

- Provider:使用mobx-react提供的Provider将所有stores注入应用;
- 使用inject将特定store注入某组件,store可以传递状态或action;然后使用observer保证组件能响应store中的可观察对象(observable)变更,即store更新,组件视图响应式更新。