我对 React Flux 架构的理解

React Flux架构简介

我的现阶段对Flux架构的理解,求拍砖求star!
原文连接:https://github.com/kuitos/kuitos.github.io/issues/27前端

React 简介请戳 这里react

Flux是什么

Flux是Facebook用来构建客户端web应用的应用架构。它利用单向数据流的方式来组合react中的视图组件。它更像一个模式而不是一个正式的框架,开发者不须要太多的新代码就能够快速的上手Flux。git

Flux的核心部分

1. dispatcher

事件调度中心,flux模型的中心枢纽,管理着Flux应用中的全部数据流。它本质上是Store的回调注册。每一个Store注册它本身并提供一个回调函数。当Dispatcher响应Action时,经过已注册的回调函数,将Action提供的数据负载发送给应用中的全部Store。应用层级单例!!github

2. store

负责封装应用的业务逻辑跟数据的交互。web

  • Store中包含应用全部的数据redux

  • Store是应用中惟一的数据发生变动的地方架构

  • Store中没有赋值接口---全部数据变动都是由dispatcher发送到store,新的数据随着Store触发的change事件传回view。Store对外只暴露getter,不容许提供setter!!禁止在任何地方直接操做Store。框架

3. view

  • controller-view 能够理解成MVC模型中的controller,它通常由应用的顶层容器充当,负责从store中获取数据并将数据传递到子组件中。简单的应用通常只有一个controller-view,复杂应用中也能够有多个。controller-view是应用中惟一能够操做state的地方(setState())异步

  • view(UI组件) ui-component 职责单一只容许调用action触发事件,数据从由上层容器经过属性传递过来。mvvm

4. 其余

action creators 做为dispatcher的辅助函数,一般能够认为是Flux中的第四部分。ActionCreators是相对独立的,它做为语法上的辅助函数以action的形式使得dispatcher传递数据更为便利。

How Flux(Unidirectional Data Flow) Works

  1. view --> actionCreators

    // Nav.jsx
    export default class Nav extends React.Component {
    
      _handleClick(nav) {
        NavActionCreators.clickNav(nav);
      }
    
      render() {
    
        let itemList = this.props.list.map((nav, index) => {
          return (
            <li className="index-menu-item" onClick={this._handleClick.bind(this, nav)} key={index}>
              <span>{nav.text}</span>
            </li>
          );
        });
    
        return (
          <nav className="index-menu">
            <ul className="index-menu-list">
              {itemList}
            </ul>
          </nav>
        );
      }
    }
  2. action dispatch

    // NavActionCreators.js
    export default {
    
      clickNav(nav){
    
        AppDispatcher.dispatch(
          {
            type: ActionTypes.CLICK_NAV,
            nav
          }
        );
      }
    };
  3. dispatcher --> store callback

    AppDispatcher.register(action => {
    
      switch (action.type) {
    
        // nav点击
        case ActionTypes.CLICK_NAV:
    
          IndexWebAPIUtils.getGiftList(_currentUserInfo.userId, action.nav.id)
            .then(function (giftList) {
    
              _currentGiftList = giftList;
              IndexStore.emitChange();
            });
    
          break;
    
        // no default
      }
    });
  4. store emitChange --> controller view --> setState

    export default class Index extends React.Component {
    
      constructor(props) {
        super(props);
        let currentUser = UserStore.getCurrentUser();
        this.state = IndexStore.getAll();
      }
    
      componentDidMount() {
        IndexStore.addChangeListener(this._onChange.bind(this));
      }
    
      componentWillUnmount() {
        IndexStore.removeChangeListener(this._onChange.bind(this))
      }
    
      _onChange() {
        this.setState(IndexStore.getAll());
      }
    
      render() {
    
        let state = this.state;
    
        return (
          <div className="page active">
            ...
            <Nav list={state.navList}/>
            ...
          </div>
        );
      }
    
    }

Flux vs MVVM

MVVM

1. 简单的MVVM

2. 复杂的MVC

Flux

1. 复杂的Flux

Flux的优点

1. 数据状态变得稳定同时行为可预测

由于angular双向绑定的缘由,咱们永远没法知道数据在哪一刻处于稳定状态,因此咱们常常会在angular中看到经过setTimeout的方式处理一些问题(其实有更优雅的解决方案,不在本次讨论以内)。同时因为双向绑定的缘由,行为的流向咱们也很难预测,当视图的model变多的时候,若是再加上一堆子视图依赖这些model,问题发生时定位简直是噩梦啊(这也是angular的错误信息那么不友好的缘由,由于框架开发者也没法肯定当前行为是谁触发的啊,绑定的人太多了...)。可是这里仍是要强调一点就是,并非说双向绑定就必定会致使不稳定的数据状态,在angular中咱们经过一些手段依然可使得数据变得稳定,只是双向绑定(mvvm)相对于flux更容易引起数据不稳定的问题。

2. 全部的数据变动都发生在store里

flux里view是不容许直接修改store的,view能作的只是触发action,而后action经过dispatcher调度最后才会流到store。全部数据的更改都发生在store组件内部,store对外只提供get接口,set行为都发生在内部。store里包含全部相关的数据及业务逻辑。全部store相关数据处理逻辑都集中在一块儿,避免业务逻辑分散下降维护成本。

3. 数据的渲染是自上而下的

view全部的数据来源只应该是从属性中传递过来的,view的全部表现由上层控制视图(controller-view)的状态决定。咱们能够把controller-view理解为容器组件,这个容器组件中包含若干细小的子组件,容器组件不一样的状态对应不一样的数据,子组件不能有本身的状态。也就是,数据由store传递到controller-view中以后,controller-view经过setState将数据经过属性的方式自上而下传递给各个子view。

4. view层变得很薄,真正的组件化

因为二、3两条缘由,view自身须要作的事情就变得不多了。业务逻辑被store作了,状态变动被controller-view作了,view本身须要作的只是根据交互触发不一样的action,仅此而已。这样带来的好处就是,整个view层变得很薄很纯粹,彻底的只关注ui层的交互,各个view组件以前彻底是松耦合的,大大提升了view组件的复用性。

5. dispatcher是单例的

对单个应用而言dispatcher是单例的,最主要的是dispatcher是数据的分发中心,全部的数据都须要流经dispatcher,dispatcher管理不一样action于store之间的关系。由于全部数据都必须在dispatcher这里留下一笔,基于此咱们能够作不少有趣的事情,各类debug工具、动做回滚、日志记录甚至权限拦截之类的都是能够的。

Flux的困境

1. 过多的样板代码

flux只是一个架构模式,并非一个已实现好的框架,因此基于这个模式咱们须要写不少样板代码,代码量duang的一会儿上来了。。不过好在目前已经有不少好用的基于flux的第三方实现,目前最火的属redux。

2. dispatcher是单例

dispatcher做为flux中的事件分发中心,同时还要管理全部store中的事件。当应用中事件一多起来事件时序的管理变得复杂难以维护,没有一个统一的地方能清晰的表达出dispatcher管理了哪些store。

3. 异步处理到底写在哪里

  • 按flux流程,action中处理:依赖该action的组件被迫耦合进业务逻辑

  • 按store职责在store中处理:store状态变得不稳定,dispatcher的waitFor失效

4. 至今尚未官方实现

写在最后

  • 前端摩尔定律:前端每18个月难度增长一倍

  • 没有银弹

相关文章
相关标签/搜索