返回 登录
0

像踢球一样玩转Redux和React

阅读2146

引言

React的核心是使用组件定义界面的表现,是一个View层的前端库,简单来说它就是一堆前端组件,view,view,view,重要的事情说三遍。

可是有了组件以后,要怎么组织前端界面的表现呢?怎么和数据交互呢?怎么管理组件与组件之间的关系呢? 嘿嘿,你猜?

Redux?是的, Redux可以做这些事情,而且做得很好!那么Redux是什么呢?怎么像踢球一样使用Redux搭建前端React应用程序?

1.Redux 应用管理服务

在了解是什么是Redux之前,可能需要先知道什么是Flux。Flux是Facebook用来构建用户端的web应用的应用程序体系架构。它通过利用数据的单向流动为React的可复用的视图组件提供了补充。

Flux应用包含三个部分:dispatcher, store, view.

单向的数据流是Flux应用的核心特性, Dispatcher,Store和View是拥有清晰的输入输出的独立节点。而Action是包含了新的数据和身份属性的简单对象。

用户的交互可能会使view产生新的action,这个action可以在整个系统中传播:

图片描述

也就是说用户操作view时产生action,action通过dispatcher分发到不同的store,store里面保存状态(state)的信息,然后view监听到store中状态的变化后,进行view的重新渲染。

可是Facebook官方的Flux实现很多人都觉得很冗余,很难让人有使用它的欲望,当然GitHub上也涌现了一批关于Flux的框架,比如:Redux, Reflux, flummox,Alt 等。其中最火,逼格最高的就是Redux。

Redux是应用状态管理服务, 它本身受到了Flux的深远影响, 但是其核心概念确很简单:

图片描述

1)actions, 用于描述View发生的事件及相关信息,且进行与数据相关的操作,并将数据传输到reducer。

2) reducers(多个reducer), reducer是一个函数:

(previousState, action) => newState

用来执行根据指定 action 来更新 state 的逻辑。reducer不存储state,也不直接改变state对象,而是返回新的state对象。

3) 只有一个store(树形结构),state 以单一对象存储在 store 对象中, 它是只读的,只能使用函数reducer对其进行更新(其实是返回新的state对象)。

2.Redux对比Reflux

在众多的关于Flux思想的类库中,Reflux 也是一个比较好的框架,它使用起来甚至比Redux更简单。它的单向数据流模式主要由actions和stores组成。

图片描述

Reflux的特点:
1) 摒弃了dispatcher

2) stores可以监听actions的行为,并负责与数据相关的内容,比如从服务器获取数据并显示的触发stores的更新

3) stores也可以互相监听,可以做一些数据聚合的操作

4) sores提供了方法供view进行监听,以更新view

从上图以及其特点看,Reflux是以store为中心的,它具有多个store,store会监听action,以及提供方法供view监听。具体的使用起来也是非常的简单。

Redux对比Reflux:

图片描述

为什么会使用Redux,而不选择Reflux呢?其实Reflux更加的适合一些中小应用,由于其store都是独立的,而且store可以相互监听,当组件比较多时,组织起来就会很混乱,而且不同的store同步也会比较麻烦。在这一点上Redux做得就比较好了,它只有一个store,记录了应用的所有状态。当然Redux对于新手来说较Reflux会难懂一些,但是其数据组织却更加清晰。而且Redux还有一个调试神器,Redux-DevTools,通过它我们可以很方便的查看应用的整个状态树,以及状态的变化过程。

3.Redux 管理前端React组件

Redux 和 React 其实是没有必然关系的,Redux 用于管理 state,与具体的 View 框架无关。Redux 可以搭配 React、Angular 甚至纯 JS。不过,Redux 特别适合那些 state => UI 的框架,比如:React,因为 React 允许以 state 的形式来描述界面,而 Redux 非常擅长控制 state 的变化。

那么Redux和 React要怎么联系起来呢?我们需要Redux的React绑定库react-redux。

react-redux提供两个关键模块:Provider和connect。

1) Provider模块是整个App的容器,需要把原有的App 根组件包括起来并接受Redux的store作为props来注入Redux store。

import ReactDOM from ‘react-dom’;
import { Component } from ‘react’;
import { Provider } from ‘react-redux’;
import rootReducer from ‘../reducers’;
import thunk from ‘redux-thunk’;
import { createStore, applyMiddleware } from ‘redux’;

class App extends Component {
render() {
// …
}
}
var store = createStore(rootReducer, applyMiddleware(thunk));
const targetEl = document.getElementById(‘root’);

ReactDOM.render(


,
targetEl
);

其中的createStore方法可以传入不同的第三方件,比如实现异步操作以及记录日志等。

2) connect模块将包装好的React组件连接到Redux 。连接操作不会改变原来的组件类,而是返回一个新的已与 Redux store 连接的组件类。

import { Component } from ‘react’;

export default class Counter extends Component {
render() {
return (

{this.props.value}

);
}
}

import { Component } from ‘react’;
import { connect } from ‘react-redux’;
import Counter from ‘../components/Counter’;
import { increment } from ‘../actions’;
import { bindActionsCreators } from ‘redux’;

// 哪些 Redux 全局的 state 是我们组件想要通过 props 获取的?
function mapStateToProps(state) {
return {
value: state.counter
};
}

// 哪些 action 创建函数是我们想要通过 props 获取的?
function mapDispatchToProps(dispatch) {
return {
onIncrement: bindActionCreators(increment, dispatch)
};
}

export default connect(
mapStateToProps,
mapDispatchToProps
)(Counter);

其中mapStateToProps是一个函数,返回值表示的是需要合并到展示组件props中的state。
mapDispatchToProps也是一个函数,返回值表示的是需要合并到展示组件props中的actionCreators。

Redux 的 React 绑定库包含了容器组件和展示组件相分离的开发思想。

明智的做法是只在最顶层组件(如路由操作)里使用 Redux。其余内部组件仅仅是展示性的,所有数据都通过 props 传入。

图片描述

关于Redux和React的关系我们再举一个生动的例子:

我们以足球举个例子,欧洲杯今天凌晨刚刚落幕,在球赛中,主要由球场,球员以及足球组成,足球运动员跟随着足球在球场上的位置是不断变化的。那么足球就相当于 Redux的state;球场和球员则相当于React组件,由于球员只能在球场跑动,所以球员就相当于展示组件,而球场则是和Redux绑定的容器组件;球员踢球的动作相当于Redux的actions。整个过程就是球员(展示组件)踢球(actions),足球的位置(state)发生变化,球员跟随着足球(state)进行相应的跑动,进而形成单向的循环。

图片描述

4.Redux在普元数字化企业云平台中的应用

我们先来看一下普元数字化企业云平台的整体逻辑图(红框标记的是前端所处的位置):

图片描述

再来看一下主前端数据流动图:

图片描述

React作为前端的界面(view),主要以组件(component)的形式存在,它会绑定Redux的actions以及state,用户操作时产生action,action此时会根据需要去Portal Server获取相关的数据,之后将数据传输到对应的reducer中,reducer作为一个函数,将得到的数据放到state中,并返回一个新的state,之后state中的部分属性会合并到组件的props中,进而进行view的更新。

普元云计算专区:http://primeton.csdn.net/m/zone/primeton/index#

普元公众号:
图片描述

评论