Flux 應用架構

Flux 應用架構

Flux是Facebook用來構建客戶端Web應用的一種應用架構體系。它是一種相似MVC的架構,可是它更加簡單、清晰,是一種單向數據流的架構設計。css

Notehtml

請事先對ReactES6進行了解。react

本文采用Facebook官方的Fluxgit

快速入門

$ git clone https://github.com/ipluser/react-flux-demo.git
$ cd react-flux-demo
$ npm start

瀏覽器將會自動打開一個新的網頁(若沒有,請訪問http://127.0.0.1:8080):es6

Demo

核心概念

Flux應用主要分爲四個主要的部門:Views, Actions, Dispatcher, Stores.github

Name Description
Views 視圖層,React組件
Actions 行爲動做層,視圖層觸發的動做,例如click event
Dispatcher 分發中心,註冊/接受動做,調用數據流向中的回調函數
Stores 數據層,管理應用狀態,廣播通知Views狀態發生改變

Flux Data Flow

單向數據流是Flux應用的核心。Dispatcher, Stores, Views是獨立的輸入和輸出節點,而Action是一個包含數據和動做類型的簡單對象。npm

Views

打開項目入口文件main.jsx:瀏覽器

// public/scripts/main.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import TodoController from './components/todoController.jsx';

ReactDOM.render(<TodoController />, document.body);

上面代碼中採用了ReactJS Controller View模式,一個"Controller View"是應用中最頂層的組件,它管理着全部應用狀態,並以屬性方式傳遞給子組件。 接下來咱們看看toToController.jsx:架構

// public/scripts/components/todoController.jsx
import React from 'react';

import TodoAction from '../actions/todoAction.js';
import TodoStore from '../stores/todoStore.js';
import Todo from './todo.jsx';

export default class TodoController extends React.Component {
  constructor(props) {
    super(props);
  }

  newItem() {
    TodoAction.addItem('new item');
  }

  render() {
    return <Todo newItem={this.newItem} />;
  }
}

正如你所看到的,TodoController僅僅給Todo子組件指定了newItem動做。Todo接收屬性和渲染組件:dom

// public/scripts/components/todo.jsx
import React from 'react';

import '../../styles/components/todo.scss';

export default function Todo(props) {
  let list = props.items.map((item, index) => {
    return <li className="color--red" key={index}>{item}</li>;
  });

  return (
    <div className="todo">
      <ul>{list}</ul>
      <button className="todo__click-btn" onClick={props.newItem}>Todo</button>
    </div>
  );
}

一旦點擊todo按鈕,TodoController將會觸發一個addItem動做。

Actions

TodoAction將數據和動做類型傳遞給Dispatcher去分發數據流:

// public/scripts/actions/todoAction.js
import AppDispatcher from '../dispatcher.js';
import TodoConstant from '../constants/todoConstant.js';

class TodoAction {
  addItem(text) {
    AppDispatcher.dispatch({
      actionType: TodoConstant.ADD_ITEM,
      text
    });
  }
}

export default new TodoAction();

todoConstants.js是一個包含全部動做類型的常量對象:

// public/scripts/constants/todoConstant.js
export default {
  ADD_ITEM: 'TODO_ADD_ITEM'
};

Dispatcher

Dispatcher一個分發中心,它管理着應用的全部數據流向。每個Store在這裏註冊,並提供一個回調函數:

// public/scripts/dispatcher.js
import { Dispatcher } from 'flux';

import TodoStore from './stores/todoStore';
import TodoConstant from './constants/todoConstant';

const AppDispatcher = new Dispatcher();

TodoStore.dispatchToken = AppDispatcher.register(payload => {
  switch (payload.actionType) {
    case TodoConstant.ADD_ITEM:
      TodoStore.addItem(payload.text);
      break;
    default:
  }
});

export default AppDispatcher;

上面代碼中能夠看到,當TodoAction提供給Dispatcher一個新動做時,TodoStore將會經過註冊時的回調函數接受動做的行爲。

Stores

TodoStore包含狀態和業務邏輯。它的職責有點相似MVC中的model

// public/scripts/stores/todoStore.js
import EventEmitter from 'events';

class TodoStore extends EventEmitter {
  constructor() {
    super();
    this.items = [];
  }

  getAll() {
    return this.items;
  }

  addItem(text) {
    this.items.push(text);
    this.change();
  }

  change() {
    this.emit('change');
  }

  addListener(name, callback) {
    this.on(name, callback);
  }

  removeListener(name, callback) {
    this.removeListener(name, callback);
  }
}

export default new TodoStore();

Views, again

再回到TodoController中,咱們初始化應用的狀態,同時監聽Store的狀態改變事件:

// public/scripts/components/todoController.jsx
import React from 'react';

import TodoAction from '../actions/todoAction.js';
import TodoStore from '../stores/todoStore.js';
import Todo from './todo.jsx';

export default class TodoController extends React.Component {
  constructor(props) {
    super(props);
    this.state = { items: TodoStore.getAll() };
    this.onListChange = this.onListChange.bind(this);
  }

  componentDidMount() {
    TodoStore.addListener('change', this.onListChange);
  }

  componentWillUnmount() {
    TodoStore.removeListener('change', this.onListChange);
  }

  onListChange() {
    this.setState({
      items: TodoStore.getAll()
    });
  }

  newItem() {
    TodoAction.addItem('new item');
  }

  render() {
    return <Todo items={this.state.items} newItem={this.newItem} />;
  }
}

一旦TodoController接受到應用狀態改變,將會觸發Todo從新渲染。

參考

源代碼

react-flux-demo

相關文章
相關標籤/搜索