当下前端流行的框架,都是用状态来描述界面(state => view),能够说前端开发实际上就是在维护各类状态(state),这已经成为目前前端开发的共识。javascript
View = ViewModel(Model);
复制代码
理想状况下,ViewModel 是纯函数,给定相同的 Model,产出相同的 View。前端
state => view 很好理解,但如何在 view 中合理地修改 state 也是一个问题。vue
图书馆的管理,原来是开放式的,全部人能够随意进出书库借书还书,若是人数很少,这种方式能够减小流程,增长效率,一旦人数变多就势必形成混乱。java
Flux 就像是给这个图书馆加上了一个管理员,全部借书还书的行为都须要委托管理员去作,管理员会规范对书库的操做行为,也会记录每一个人的操做,减小混乱的现象。react
咱们寄一件东西的过程git
没有快递时:github
有了快递公司:vuex
多了快递公司,让快递公司给咱们送快递。数据库
当咱们只寄送物品给一个朋友,次数较少,物品又较少的时候,咱们直接去朋友家就挺好的。但当咱们要频繁寄送给不少朋友不少商品的时候,问题就复杂了。编程
软件工程的本质便是管理复杂度。使用状态管理类框架会有必定的学习成本并且一般会把简单的事情作复杂,但若是咱们想作复杂一点的事情(同时寄不少物品到多个不一样地址),对咱们来讲,快递会让复杂的事情变的简单。
这同时也解释了,是否须要添加状态管理框架,咱们能够根据本身的业务实际状况和技术团队的偏好而添加,有些状况下,建立一个全局对象就能解决不少问题。
Redux store 是单一数据源。Redux 没有 dispatcher 的概念,转而使用纯函数(pure function)代替。
Redux store 是不可变的(Immutable)。
和 Redux 对单向数据流的严格规范不一样,Mobx 只专一于从 store 到 view 的过程。在 Redux 中,数据的变动须要监听,而 Mobx 的数据依赖是基于运行时的,这点和 Vuex 更为接近。
Facebook 提出了 Flux 架构思想,规范了数据在应用中的流动方式。其基本架构以下入所示,其核心理念是单向数据流,它完善了 React 对应用状态的管理。
上图描述了页面的启动和运行原理:
1.经过 dispatcher 派发 action,并利用 store 中的 action 处理逻辑更新状态和 view
2.而 view 也能够触发新的 action,从而进入新的步骤 1
其中的 action 是用于描述动做的简单对象,一般经过用户对 view 的操做产生,包括动做类型和动做所携带的所需参数,好比描述删除列表项的 action:
{
type: types.DELETE_ITEM,
id: id
};
复制代码
而 dispatcher 用于对 action 进行分发,分发的目标就是注册在 store 里的事件处理函数:
dispatcher.register(function(action) {
switch (action.type) {
case "DELETE_ITEM":
sotre.deleteItem(action.id); //更新状态
store.emitItemDeleted(); //通知视图更新
break;
default:
// no op
}
});
复制代码
store 包含了应用的全部状态和逻辑,它有点像传统的 MVC 模型中的 model 层,但又与之有明显的区别,store 包括的是一个应用特定功能的所有状态和逻辑,它表明了应用的整个逻辑层;而不是像 Model 同样包含的是数据库中的一些记录和与之对应的逻辑。
参考连接:flux
原生 Redux API 最简单的用例
function counter(state, action) {
if (typeof state === "undefined") {
return 0;
}
switch (action.type) {
case "INCREMENT":
return state + 1;
case "DECREMENT":
return state - 1;
default:
return state;
}
}
var store = Redux.createStore(counter); //
var valueEl = document.getElementById("value");
function render() {
valueEl.innerHTML = store.getState().toString();
}
render();
store.subscribe(render);
document.getElementById("increment").addEventListener("click", function() {
store.dispatch({ type: "INCREMENT" });
});
document.getElementById("decrement").addEventListener("click", function() {
store.dispatch({ type: "DECREMENT" });
});
document.getElementById("incrementIfOdd").addEventListener("click", function() {
if (store.getState() % 2 !== 0) {
store.dispatch({ type: "INCREMENT" });
}
});
document.getElementById("incrementAsync").addEventListener("click", function() {
setTimeout(function() {
store.dispatch({ type: "INCREMENT" });
}, 1000);
});
复制代码
应用中全部的 state 都以一个对象树的形式储存在一个单一的 store 中。 改变 state 的惟一办法是触发 action,一个描述发生什么的对象。 为了描述 action 如何改变 state 树,你须要编写 reducers。
单一数据源
整个应用的 state
被储存在一棵 object tree 中,而且这个 object tree 只存在于惟一一个 store
中。
state 是只读的
惟一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。
使用纯函数来执行修改
为了描述 action 如何改变 state tree ,你须要编写 reducers
。 改变 state
的唯一方法是 dispatch action
。你也能够 subscribe
监听 state
的变化,而后更新 UI。
严格的单向数据流是 Redux 架构的设计核心。
Redux 的 API 很是少。
Redux 定义了一系列的约定(contract)来让你来实现(例如 reducers),同时提供少许辅助函数来把这些约定整合到一块儿。
Redux 只关心如何管理 state。在实际的项目中,你还须要使用 UI 绑定库如 react-redux。
在写 redux 的 action 的时候,老是须要用到扩展语句或者 Object.assign()
的方式来获得一个新的 state,这一点对于 JavaScript 而言是对象的浅拷贝,它对内存的开销确定是大于 mobX 中那样直接操做对象属性的方式大得多。
参考连接:redux-immutable seamless-immutable reselect 为何使用 Redux 管理状态是可预测的
redux 是 react 技术栈中的状态控制流框架,使用了标准的函数式思想,指望(强制)全部状态管理都是纯函数。这也意味着各状态之间都是独立的。可是有一类状态 redux 直接甩给了的第三方模块,反作用模块 redux-saga
也就成了不辞辛苦的典型表明。反作用正是由于不肯定性和可变性而得名,而其给出的状态又是相互影响,如何解耦使得本来复杂的非线性呈现为线性逻辑,正是有限状态机的用武之处。
dva 首先是一个基于 redux
和 redux-saga
的数据流方案,而后为了简化开发体验,dva 还额外内置了 react-router
和 fetch
,因此也能够理解为一个轻量级的应用框架。
在 redux 的生态圈内,每一个环节有多种方案,好比 Data 能够是 immutable 或者 plain object,在你选了 immutable 以后,用 immutable.js 仍是 seamless-immutable,以及是否用 redux-immutable 来辅助数据修改,都须要选择。
MobX 是一个用法简单优雅、同时具备可扩展性的状态管理库。
import { observable, autorun } from "mobx";
const appState = observable({
counter: 0,
add(value) {
this.counter += value;
}
});
autorun(() => console.log(appState.counter));
setInterval(() => appState.add(1), 1000);
复制代码
在 mobx 中咱们能够直接修改状态
import { observable } from "mobx";
const appState = observable({ counter: 0 });
appState.counter += 1;
复制代码
能够经过引入 Strict 模式来避免这种不良好的实践:
import { useStrict } from "mobx";
useStrict(true);
复制代码
MobX 脱胎于响应式编程(Reactive Programming),其核心思想为 Anything that can be derived from the application state, should be derived. Automatically,即避免任何的重复状态。
MobX 中核心的概念便是 Observable,相信接触过响应式编程的确定很是熟悉,从后端的典型表明 RxJava 到 Android/iOS 开发中的各类响应式框架都各领风骚。
Redux / MobX 均为客户端开源状态管理库,用状态来描述 UI 界面,它们与 React 都不具备强绑定关系,你也能够配合别的框架来使用它们。 固然,与 React 是再合适不过的了,React 做为 View 层的框架,经过 Virtual DOM 机制来优化 UI 渲染,Redux / MobX 则提供了将相应状态同步到 React 的机制。
Redux 与 MobX 的不一样主要集中于如下几点:
shouldComponentUpdate
优化。而 MobX 只自动更新你所关心的,没必要担忧嵌套带来的重渲染问题。Mobx 最关键的函数在于 autoRun,autoRun 的专业名词叫作依赖收集,也就是经过天然的使用,来收集依赖,当变量改变时,根据收集的依赖来判断是否须要更新。Mobx 使用了 Object.defineProperty
拦截 getter 和 setter,和 Vue 同样。
Vuex 是专门为 Vue.js 设计的状态管理库。把组件的共享状态抽取出来,以一个全局单例模式管理。它采用集中式存储管理应用的全部组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
Vuex 的用法很简单, 一句话总结:commit mutation,dispatch action
参考连接:Vuex 官方文档
有限状态机(finite-state machine)又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动做等行为的数学模型,很是有用,能够模拟世界上大部分事物。
有限状态机并非一个复杂的概念,简单说,它有三个特征:
使用状态去影响视图,而 Action 主要负责完成状态间的变动。代码如何更好的构建其核心在于使用最合理的状态去管理界面,并用最合理的动做去实现状态间的变动。
所谓的状态管理,实际上就是使用有限状态机来管理前端状态。
有限状态机对 JavaScript 的意义在于,不少对象能够写成有限状态机。
写代码以前,思考一下:
而后跟着思路,完成数据与 UI 部分。
参考连接:javascript-state-machine xstate managing-state-in-javascript-with-state-machines-stent