Open sunnychuai opened 4 years ago
Store 就是保存数据的地方,你可以把它看成一个容器。整个应用只能有一个 Store。 Store 就是管理action和reducer及其关系的对象。 Redux 提供createStore这个函数,用来生成 Store。 Store 提供了三个方法
let unsubscribe = store.subscribe(() => console.log(store.getState()) );
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更新,组件视图响应式更新。
Redux 的设计思想
Store
Store 就是保存数据的地方,你可以把它看成一个容器。整个应用只能有一个 Store。 Store 就是管理action和reducer及其关系的对象。 Redux 提供createStore这个函数,用来生成 Store。 Store 提供了三个方法
unsubscribe();
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 }; };
const action = { type: 'ADD_TODO', payload: 'Learn Redux' };
const reducer = function (state, action) { // ... return new_state; };
// State 是一个对象 function reducer(state, action) { return Object.assign({}, state, { thingToChange }); // 或者 return { ...state, ...newState }; }
// State 是一个数组 function reducer(state, action) { return [...state, newItem]; }