Flux是Facebook用來構建客戶端Web應用的一種應用架構體系。它是一種相似MVC的架構,可是它更加簡單、清晰,是一種單向數據流的架構設計。css
Notehtml
本文采用Facebook官方的Flux。git
$ git clone https://github.com/ipluser/react-flux-demo.git $ cd react-flux-demo $ npm start
瀏覽器將會自動打開一個新的網頁(若沒有,請訪問http://127.0.0.1:8080
):es6
Flux應用主要分爲四個主要的部門:Views, Actions, Dispatcher, Stores.github
Name | Description |
---|---|
Views | 視圖層,React組件 |
Actions | 行爲動做層,視圖層觸發的動做,例如click event |
Dispatcher | 分發中心,註冊/接受動做,調用數據流向中的回調函數 |
Stores | 數據層,管理應用狀態,廣播通知Views狀態發生改變 |
單向數據流是Flux應用的核心。Dispatcher, Stores, Views是獨立的輸入和輸出節點,而Action是一個包含數據和動做類型的簡單對象。npm
打開項目入口文件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動做。
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一個分發中心,它管理着應用的全部數據流向。每個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將會經過註冊時的回調函數接受動做的行爲。
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();
再回到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從新渲染。