React 實踐記錄 04 Flux demo

Introduction

flux應用架構以下圖所示,本文並非講述怎麼當即作一個酷炫的應用,而是講述如何依照這種框架,來進行代碼的組織。

咱們先把這個流程轉述爲文字:拋開與webAPI的交互不談,之後的文章再介紹。
flux應用的數據流是單向的,從咱們以前最熟悉的React組件看起,它們構成了上圖中的React Views。用戶交互可使得Action Creators建立Action,交由Dispatcher分發。根據已註冊的Store信息,Dispathcer管理依賴,完成分發,而Store會觸發數據改變的事件,偵聽該事件的React Views即會進行Store Queries,拿到數據。
本文以完成下圖的功能爲例,一個能夠添加item的表單。若是不套flux用的代碼少的多,可是,這樣的例子適合用於講解flux而非專一於其它細節(複雜應用將更偏重於React 組件的設計,於本文中心偏離)。

源碼已經上傳:https://github.com/EcutDavid/fluxDemocss

搭建目錄,文件結構

mkdir script && cd script 
 mkdir actions components dispatcher stores constants
 cd ..
 touch entry.js index.html webpack.config.js

關於webpack,博主的webpack系列文章已經介紹,再此,再也不贅述。
安裝moudles(關於moudles的選型,仁者見仁,智者見智,無需拘束於如下的例子)。html

npm init 
npm install babel-loader css-loader style-loader flux react keymirror events obejct-assign --save

Dispatcher

flux中, Dispatcher是單例的,因此,直接向下面代碼同樣返回一個實例。以後,Action與Store都會用到它們。前端

script/dispatcher/dispatcher.jsreact

var Dispatcher = require('flux').Dispatcher;

module.exports = new Dispatcher();

Action

實現一個枚舉,用於定義全部的Action類型,藉助於keymirror實現webpack

script/constants/appConstants.jsgit

var keyMirror = require('keymirror');

module.exports = new keyMirror({
  CREATE: null
});

ActionCreator要藉助dispatcher來分發action。github

script/actions/appActionCreator.jsweb

"use strict"

var dispatcher = require('../dispatcher/dispatcher');
var appConstants = require('../constants/appConstants');

var appActionCreator = {
  create: function(text) {
    dispatcher.dispatch({
      actionType: appConstants.CREATE,
      text: text
    });
  }
};

module.exports = appActionCreator;

Store

Store中,咱們須要向dispatcher註冊並處理dispatcher分發過來的action,提供接口使得view能夠偵聽數據變化,查詢數據。npm

script/stores/appStore.jsbabel

"use strict"
var dispatcher = require('../dispatcher/dispatcher');
var EventEmitter = require('events').EventEmitter;
var appConstants = require('../constants/appConstants');
var assign = require('object-assign');

var CHANGE_EVENT = 'change';
var textList = [];

var appStore = assign({}, EventEmitter.prototype, {
  create: function(text){
    textList.push(text);
  },
  getAll: function() {
    return textList;
  },
  emitChange: function() {
    this.emit(CHANGE_EVENT);
  },
  addChangeListener: function(callback) {
    this.on(CHANGE_EVENT, callback);
  },
  removeChangeListener: function(callback) {
    this.removeListener(CHANGE_EVENT, callback);
  }
});

dispatcher.register(function(action) {
  switch(action.actionType) {
    case appConstants.CREATE:
      appStore.create(action.text);
      appStore.emitChange();
      break;
    default:
  }
});

Views

在view中,咱們偵聽store的數據變化,在用戶交互時,發出action。

"use strict"
var React = require('react');
require('../../style/main.css');
var appActionCreator = require('../actions/appActionCreator');
var appStore = require('../stores/appStore');

var App = React.createClass({
  componentDidMount: function(){
    appStore.addChangeListener(this._onChange);
  },
  componentWillUnmount: function(){
    appStore.removeChangeListener(this._onChange);
  },
  _onChange: function(){
    var arr = appStore.getAll();
    this.setState({'infoList': arr});
  },
  getInitialState:function(){
    var arr = appStore.getAll();
    return({'infoList': arr});
  },
  add: function(){
    appActionCreator.create(React.findDOMNode(this.refs.textArea).value);
  },
  render: function(){
    var textList = this.state.infoList.map(function(item){
      return <p>{item}</p>;
    });
    return(
      <div className="container">
        <input ref="textArea" type="text"></input>
        <button className="button" onClick={this.add}>add</button>
        {textList}
      </div>
    );
  }
});

module.exports = App;

entry.js

var React = require('react');
var App = require('./script/components/app');

React.render(<App />, document.body);

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <script src="bundle.js"></script>
  </body>
</html>

效果:
dispatcher還能夠管理sotre之間的依賴, 藉助react,咱們還能夠開發不少易維護的前端組件。 本文是一個完整的flux應用的例子,側重的是代碼,flux的理念請看博主的其它文章 :)

相關文章
相關標籤/搜索