像踢球一样玩转Redux和React

转载本文需注明出处:EAII企业架构创新研究院,违者必究。如需加入微信群参与微课堂、架构设计与讨论直播请直接回复此公众号:“加群 姓名 公司 职位 微信号”。


引言

        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可以在整个系统中传播:


0?wx_fmt=png


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


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


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


0?wx_fmt=png


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组成。


0?wx_fmt=png


Reflux的特点:

1) 摒弃了dispatcher 


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


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


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


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



    Redux对比Reflux:



ReduxReflux
store只有一个,以state形式存在有多个store
数据相关操作在actions中进行在store中进行
返回数据返回一个新的state返回修改的store
组件获取数据将state合并到组件的props中直接修改组件的state


为什么会使用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(
    <Provider store={store}>
        <App />
    </Provider>,
    targetEl
);

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


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


import { Component } from 'react';

export default class Counter extends Component {
    render() {
        return (
            <button onClick={this.props.onIncrement}>
                {this.props.value}
            </button>
        );
    }
}

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
读取数据从Redux获取state从props获取数据
修改数据向Redux派发actions从props调用回调函数


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

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



0?wx_fmt=png


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


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


0?wx_fmt=jpeg

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


0?wx_fmt=png


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


5. 附录


Redux 中文文档:http://cn.redux.js.org/
Redux-DevTools: https://github.com/gaearon/redux-devtools


关于作者:

郭怀成

现任普元SOA产品部高级软件开发工程师,为普元新一代数字化企业云平台的一员,目前专职前端开发,对前端技术有着浓厚的兴趣。

0?wx_fmt=jpeg


关于EAII

EAII(Enterprise Architecture Innovation Institute)企业架构创新研究院,致力于软件架构创新与实践,加速企业数字化转型。


eaworld项目(微信号:eaworld,长按二维码关注)

640?wx_fmt=jpeg

eaworld是EAII的官方微信账号。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值