【天赢金创】React flux九浅一深

前端之家收集整理的这篇文章主要介绍了【天赢金创】React flux九浅一深前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

这个是 Facebook 官方学习 Flux 的 todo 例子

想用这个例子来总结一下怎么从零开始用 React 和 Flux 构建一个 App

Structure

App
├─ javascripts
│  ├─ actions
│  │  ├─ TodoActions.js
│  ├─ components
│  │  ├─ TodoComponents
│  │  │  ├─ TodoApp.js
│  │  │  ├─ Header.js
│  │  │  ├─ MainSection.js
│  │  │  ├─ Footer.js
│  │  │  ├─ TodoItem.js
│  │  │  ├─ TodoTextInput.js
│  ├─ constants
│  │  ├─ TodoConstants.js
│  ├─ dispatcher
│  │  ├─ AppDispatcher.js
│  ├─ stores
│  │  ├─ TodoStore.js
├─ stylesheets
│  ├─ TodoStyle.css
├─ index.html
├─ README.md
├─ package.json
├─ webpack.config.js

可能你看到的这个结构和官方 demo 的结构会有点不同,那是因为官方的 demo 整个的本身只有 todo 这个功能,但实际上远远不至。所以在 components 下会细分是什么部分的组件,像 TodoComponents

关于 Flux 里的 Action,Dispatcher,Store and Controller View 这些概念如果还不了解的话可以去看看这两篇文章

Components

首先你通过你 app 的界面来确定你的组件,如下图

从这个图我们可以看到,我们的组件有

  • Header
  • MainSection
  • Footer
  • TodoItem
  • TodoTextInput

在 MainSection 里有 TodoTextInput 是当我们双击我们已经存在的 todo,可以对其进行更新

Actions

确定了组件之后,我们就可以确定我们的 TodoActions 文件了。

对于这个 Todo app,有多少 actions 呢?

  • create- 我们可以创建一条新的 todo
  • updateText- 双击已经存在的 todo,可以对其进行更新
  • toggleComplete- 看到每一条前面的勾勾了吗?就是可以给你决定是否完成了
  • toggleCompleteAll- 看到输入框前面那个 » 了吗?就是让你全部完成,或者全部不完成的
  • destroy- 看到每一条后面那个叉叉了吗?要 hover 在上面才看到的,就是给你删除这一条的
  • destroyCompleted- 看到 Footer 下面那个 Clear completed 了吗?就是给我们删除已经完成的 todo 的

就是这样,我们根据我们的需求在这个文件里定义不同的 action 函数,但这里的函数并不涉及逻辑的处理,这里函数只是告诉我们的 Dispatcher,用户进行了什么操作。所以我们只需要给 Dispatcher 传的一个对象,对象里一个必要的属性就是 actionType。如果用户进行这个操作有给我们传的参数的话。那参数也会放在这个对象里。

例如用户想创建一条新的 todo ,就是我们的createaction 了

import AppDispatcher from '../dispatcher/AppDispatcher'; import TodoConstants from '../constants/TodoConstants'; var TodoActions = {
  create (text) {
    AppDispatcher.dispatch({
      actionType: TodoConstants.TODO_CREATE,text: text
    });
  },// other actions } export default TodoActions;

当我们执行 AppDispatcher.dispatch 这个方法,并传给他一个有 actionType 属性的对象时,他就会在大喊,“有人做了一个操作呀,这个操作就是 xxx (actionType 的值),还带了个参数,你们哪个来处理一下呀”

嗯嗯,就是这样,数据就从 Action 传到了 Dispatcher

Dispatcher

Dispatcher 的具体实现可以看 github.com/facebook/flux/blob/master/src/Dispatcher.js

游客只可以贴两个链接,我也是醉

当我们用 Facebook 给我们提供的 Dispatcher,那么一切都会变得简单了许多

npm install --save flux
import Flux from 'flux'; var Dispatcher = Flux.Dispatcher; export default new Dispatcher();

Dispatcher 在整个应用

只有一个,只有一个,只有一个

有人就说了,你 Dispatcher 只负责喊的,我不要你也好像可以呀。嗯嗯,那就不叫 Fulx 了,叫 Reflux github.com/spoike/refluxjs

Constants

刚刚我们看到在我们的 Actions 里,actionType: TodoConstants.TODO_CREATE,这个 TodoConstants 其实就是我们操作的名字,相当于一个常量,定义在 Constants 里方便管理和调用而已。

一般你有多少个 action,就有多少个常量在这个 Constants 里

KeyMirror 就是创建一个对象,里面键的值等于键的名字 - -

Stores

主角登场! 但, Store 是什么?

Store 是一个保存数据的地方

var _todo = {};

Store 是一个充满逻辑的地方

所有 actions 的逻辑处理,都会在这里发生。像我们的createaction

function create (text) { var id = (new Date() + Math.floor(Math.random() * 999999)).toString(36);
  _todos[id] = {
    id: id,complete: false,text: text
  };
}

Store 是一个响应 Dispatcher 呼喊的地方

“有人做了一个操作呀,这个操作就是 xxx (actionType 的值),还带了个参数,你们哪个来处理一下呀”

在 Store 里,我们通过 Dispatcher “注册”了一个回调函数,每当我们调用 dispatch 函数的时候,就是 Dispatcher 大喊的时候,我们根据不同的 actionType,来调用我们不同的逻辑处理函数,像这样

import AppDispatcher from '../dispatcher/AppDispatcher'; import TodoConstants from '../constants/TodoConstants';

AppDispatcher.register((action) => { var text; switch(action.actionType) { case TodoConstants.TODO_CREATE:
      text = action.text.trim(); if (text !== '') {
        create(text);
        TodoStore.emitChange();
      } break; // other case }
});

Store 是一个鞭策 Controller View 改变的地方

每当 Store 改变了数据之后,他都要 Controller View 跟着他改变。他们还约定了暗号

var CHANGE_EVENT = 'change';

Store 跟 Controller View 说,我一喊 “变”,你听到之后,你就叫你的手下一起变。

Controller View 说好。

但是 Store 不会喊,Controller View 也听不到。

所以 Store 从EventEmitter中学会了喊,也给 Controller View 买来了助听器

import assign from 'object-assign'; var EventEmitter = require('events').EventEmitter; var TodoStore = assign({},EventEmitter.prototype,{
  areAllComplete () { for (var id in _todos) { if (!_todos[id].complete) { return false;
      }
    } return true;
  },getAll () { return _todos;
  },emitChange () { this.emit(CHANGE_EVENT);
  },addChangeListener (callback) { this.on(CHANGE_EVENT,callback);
  },removeChangeListener (callback) { this.removeListener(CHANGE_EVENT,callback);
  }
}); export default TodoStore;

所以每当执行完逻辑处理函数之后,Store 都会喊一句TodoStore.emitChange();

助听器addChangeListener (callback) { this.on(CHANGE_EVENT,callback) }也买好了,成不成功,就看 Controller View 了

Controller View

在 Components 里,你看不到 TodoApp 这个组件,因为对于 Todo 这个 App,TodoApp 这个组件,就是 Contriller View,他掌管全部的 Components。

但是重要的是,他怎么带 Store 给他买的助听器

componentDidMount () {
  TodoStore.addChangeListener(this._onChange.bind(this));
}

当组件渲染完成后,就绑定了 Store 的addChangeListener,并回调了自己的onChange方法

_onChange () { this.setState(this.getTodoState.bind(this)());
}

Store 一喊,Controller View 听到之后,更新所有数据,以props的方式传给他的手下 - 即他掌管的 Components

Summary

现在我们来疏理一下整个流程(就 create 而言)

  1. 用户输入要新增的 todo,一敲回车,触发onKeydown方法
  2. onKeydown调用了onSave方法,onSave调用了TodoActions.create方法
  3. TodoActions.create触发了AppDispatcher.dispatch方法,AppDispatcher 大喊了一声。
  4. TodoStore 响应,根据 actionType 调用了create逻辑处理函数,执行完,喊了一句 “变”。
  5. Controller View 带着助听器听到了接着更新数据,把数据传给了各个 Components。
  6. 重新渲染,新增完毕。

以上是本人浅显的理解,如有错误,欢迎指正 : )

猜你在找的React相关文章