React官方网站是这样形容React的,A JavaScript library for building user interfaces。React其实是一个编写页面的UI框架,或者说他只是一个UI的library,一个库而已。html
虽然React只是一个UI的library,不过他渲染页面的方式倒是值得咱们学习的。经过JSX动态的生成DOM来渲染页面UI。他没有架构,没有模板,没有设计模式,没有路由,也没有数据管理,也能够说他除了渲染UI之外什么都作不了。npm
可是对于一个大型的复杂的网站来讲,设计模式和数据管理这两个是缺一不可的,所以若是咱们只使用React是没有办法开发大型网站应用的。redux
好比下面这张图,他表明的是React的组件结构,网站是经过组件树的形式渲染UI的。设计模式
咱们都知道React中数据流向是单向的,并且老是自上而下传递的,能够经过props将数据从父组件传递给子组件,可是假设咱们须要将组件树最底层的Banner节点的数据传递给最顶层的Index,这个时候组件之间该如何通讯呢。微信
遵循React的单向数据传递原则咱们是没有办法直接传递数据的不过咱们能够经过函数回调的方式,经过调用父组件的函数一层一层的向上传递。也就是Banner调用回调将数据传给Main,Main再经过回调将数据传给Index。markdown
实际上在大型的网站中相似这样须要共享数据的状况很是常见,若是咱们经过回调函数这样来一层一层传递你会发现整个网站的代码会变得很是恶心。基本上你的代码就是没法维护的状态。并且这样处理数据的开销是很是巨大的。一个不当心颇有可能陷入无限死循环中。架构
因此当咱们的网站复杂到必定程度的时候咱们就须要设计模式了,可能以前你已经知道MVC, MVVM, MV*。可是针对React咱们还可使用一种更加符合React设计思想的架构模式,Redux。框架
Redux是一种设计模式同时也是一种项目架构方案,他不依赖任何库或者任何框架,他不只能够在React中使用甚至在Angular和Vue中也可使用。异步
使用Redux架构来讲全部的组件基本不会互相通讯了,数据放在一个叫作store的数据仓库中存储。函数
经过使用Redux咱们能够剥离出组件中的数据(state),将全部数据统一存放在Redux数据(store)仓库中,若是组件中哪个组件须要使用到数据,这个组件能够去数据仓库中自行认领有个高大上的叫法是订阅。若是组件中对store中的数据进行了更新那么store会向订阅了这个数据的全部组件推送最新的数据,这就是Redux的原理。
Redux就是数据仓库,他把数据统一保存起来,在隔离的数据和UI的同时还处理了他们之间的关系。
使用Redux的目的是让状态state的变化可控可预测。虽然从原理来看Redux彷佛挺简单的可是想要了解他的工做流程就比较麻烦了。
这主要是由于他的数据流动方式不是特别直观,有点相似事件驱动的方式,咱们知道事件驱动开发最困难的地方是在调试。Redux中使用了不少晦涩难懂的专业术语好比Action,Reducer,Dispatch等,了解这些名词以前咱们很难把握Redux的方向。还有就是Redux的文档并不亲民,处处都是新概念,好比说纯函数,flux,observable,immutable这些概念张口就来彻底不去考虑别人是否能够看懂。
通常来讲使用Redux都会建立一个用于存放数据的Store,在这个Store中有若干个Reducer,而后咱们须要使用React组件来渲染UI,除此以外还会有若干个和Reducer对应的Action指令。
Store中的Reducer组合在一块儿就造成了项目中的数据仓库。Redux称之为State也就是数据。React组件经过订阅(subscribe )Store来得到数据,而后使用数据来渲染UI,UI经过显示器显示给用户,用户经过鼠标和键盘与组件进行交互,在交互中不可避免须要改变数据,在React中数据的流动是单向的,因此对数据来讲React组件只有读取权限,没有书写权限UI组件不能够直接访问Store修改数据。
因此UI必须向Store发送Action指令,来让Store本身修改本身,这个指令的分发过程就叫作dispatch。Action指令到达store以后可能会通过若干个middleware中间件进行数据的预处理,对于数据的异步处理也是在这里进行的,预处理事后数据就会连同action一块儿传递给reducer,reducer会按照Action中描述的指令来更新数据state,当state更新好之后Store就会把数据推送给订阅了本身的组件,组件会根据新的数据从新渲染UI, 用户就能看到变化了。能够看到在实际工做中Redux架构仍是相对复杂的。
上面的描述仍是比较复杂的,不过不要慌,下面咱们来简化一下这张图,只保留几个主要部件,经过学习简化的流程来了解Redux。
简化后的六层咱们只保留Reducer,Store,React组件,Actions这四个部分。为了更加清晰咱们这里将Reducer从Store中移了出来,实际上他们是一体的。
Store中保存的是全局数据,对于Redux项目来讲有且只有一个Store,咱们能够把它看作一个带有推送功能的数据仓库。咱们能够借用微信的朋友圈来理解这个概念。好比你加了某我的的好友,只要这我的一发朋友圈他的状态就会立刻推送到你。加好友就是数据订阅,发朋友圈就是数据推送。
Reducer是帮助Store处理数据的方法,他是一个方法是一个过程是一个函数不是一个具体存在的对象,Reducer能够帮助Store初始化数据,修改数据,删除数据,你可能会好奇咱们为何要使用Reducer这么麻烦的方式来处理数据而不是直接在Store中进行修改,其实缘由也很简单。好比你看到你朋友的朋友圈有错别字,你是没办法直接修改它的朋友圈状态的。
任何UI级别的组件都没有权限修改Store中的数据,根据数据单向流动的原则他们是只读不能写的,你只能给他打电话或者发短通知他让他来修改,他修改后会重新推送给你。给他打电话或者发短信通知他就是Action,给他打电话或者发短信通知他的这个过程就是dispatch Action消息的分发。他本身修改朋友圈的过程就是reducer。
最后他修改好以后微信会重新将消息通送给你,这就是订阅和推送。
因此Store就是Redux中具备推送功能的数据仓库,Reducer是Store处理数据的方法能够帮助Store实现数据的初始化,修改或者删除,Actions就是数据更新的指令,他会告诉Reducer如何去处理数据因此Redux的流程其实很清晰。
首先建立数据仓库Store,Reducer会同时初始化数据state。React Component会订阅Store,Store中的数据就会被推送过来,而后渲染UI.
若是组件须要更改数据他会发送一个Action,这个过程就叫作dispatch。Action会以事件驱动的方式被Store所截获,Store会将本身当前的数据以及指令传递给Reducer,由Reducer去更新数据。Reducer更新完成之后就会向Store输出一个新的state,Store取到新的state以后就会向订阅了本身的React组件推送这个新的数据。而后从新再次渲染UI。这就是一个完整的Redux工做流程。
Redux是一种设计模式同时也是一种项目架构方案,他不依赖任何库或者任何框架,只是你们习惯于将Redux和React放在一块儿使用。这里咱们介绍一下Redux的使用,为了不混淆咱们不使用任何框架。
首先你能够经过npm在项目中安装redux插件,前面说过Store就是保存数据的地方,整个应用只能有一个Store, Redux提供createStore这个函数,用来生成Store。
import { createStore } from 'redux'
const store = createStore(fn);
复制代码
这里createStore须要接收一个函数,这个函数就是用来处理action操做的也就是咱们以前说的Reducer,因此他须要接收action参数,由于他是帮助Store处理数据的,因此也须要接收源数据,返回值是更新后的数据。
const fn = (state = 0, action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}
复制代码
在须要使用数据的位置咱们能够经过getState来获取数据,经过subscribe订阅来监听数据的变化,由于Redux是一种发布订阅模式,只有监听才会获取到。
store.subscribe(() => {
const state = store.getState();
}))
复制代码
须要更数据时,须要使用dispatch配合action来分发。咱们约定action须要是一个拥有type属性的对象,type来表示要操做的类型,若是传递参数咱们通常将参数放在payload属性中。
const action = {
type: 'INCREMENT',
payload: '参数',
};
store.dispatch(action);
复制代码
这样咱们当调用store.dispatch时,Redux会将action传递给Reducer,Reducer经过自身的逻辑处理返回新的state,而后Redux记录这个新的state而且推送消息给订阅了本身的组件。也就是会触发subscribe中传入的函数。函数中能够经过store.getState()得到新的state值,完成页面更新。
假设咱们页面中有一个button按钮和一个div元素,这个元素用来展现一个数字,初始值为0,当咱们点击button按钮的时候让div中显示的数字增长。
<div id="count"></div>
<button id="button">按钮</button>
复制代码
js代码以下, 咱们首先定义reducer,在里面判断若是type为INCREMENT就让state+1,而后经过createStore建立store传入处理函数reducer。
接着订阅state,当state变动时获取页面div元素更新div的内容为state的值。
最后点击按钮的时候咱们经过dispatch来分发action。
var reducer = (state = 0, action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1
default:
return state
}
}
var store = createStore(reducer);
store.subscribe(() => {
document.querySelector('#count').innerHTML = store.getState();
});
document.querySelector('#button').addEventListener('click', function () {
store.dispatch({type: 'INCREMENT'});
});
复制代码
这就是Redux的一个基本使用过程,你懂了么?
那具体何时须要使用到Redux呢?
组件须要共享数据或者共享状态(state)的时候;
某一个组件在任何地方都须要被随时访问的时候。
某一个组件须要改变另外一个组件状态的时候。
网站支持国际化语言切换,登陆数据共享的状况下。
知足上面一种或几种状况建议使用redux,若是你还在考虑项目要不要使用redux我给的建议就是不要。技术是为了服务业务。为了不设计的头重脚轻,建议只有在须要的时候才引入新概念,切忌为了使用而使用。