React系列之 Flux架構模式

原文地址:https://gmiam.com/post/react-...html

因爲 React 只涉及 UI 層的處理,因此構建大型應用應該搭配一個框架模式才能使後期維護成本相對較小~react

Flux 正是 FB 官方給出的應用架構,他推崇一種單向的數據流動模式,看下圖感覺下git

da0d759007d119b9bb94140776651096.png

整個流程是github

  • 用戶與 View 層交互,觸發 Actionapi

  • Action 使用 Dispatcher 進行分發架構

  • Dispatcher 觸發 Store 回調進行更新mvc

  • Store 更新觸發 View 層事件app

  • View層 收到信號進行更新框架

相對傳統 MV* 模式,Flux 一個最大的特點就是單向的數據流讓事情變的可預見,看下面大型應用圖感覺下不一樣dom

MV*

alt

Flux

alt

其實概念說了一堆仍是比較難理解,你們能夠配合 flux-todomvc 官方示例來直觀感覺理解下

app.js 渲染的是 TodoApp.react.js 這個組件,組件內部從 TodoStore 獲取數據傳遞給子組件,同時監聽了 TodoStore 的數據變化,FB 管這種頂層 View 叫作 Controller-View

TodoApp.react.js

var TodoStore = require('../stores/TodoStore');

function getTodoState() {
  return {
    allTodos: TodoStore.getAll(),
    areAllComplete: TodoStore.areAllComplete()
  };
}

var TodoApp = React.createClass({

  getInitialState: function() {
   // 獲取初始數據
    return getTodoState();
  },

  componentDidMount: function() {
    // 監聽數據變化
    TodoStore.addChangeListener(this._onChange);
  },

  render: function() {
    return (
      <div>
        <Header />
        <MainSection
          allTodos={this.state.allTodos}
          areAllComplete={this.state.areAllComplete}
        />
        <Footer allTodos={this.state.allTodos} />
      </div>
    );
  },

  _onChange: function() {
    this.setState(getTodoState());
  }

});

TodoApp.react.js 又嵌套了幾個子組件,這裏咱們關注下 Header.react.js 這個子組件感覺一下整個流程就行了

Header.react.js 的子組件 TodoTextInput.react.js 監聽 dom 輸入框的各類事件,觸發父組件傳遞給他的 Action 方法

Header.react.js

var TodoTextInput = require('./TodoTextInput.react');

var Header = React.createClass({
  render: function() {
    return (
      <header id="header">
        <h1>todos</h1>
        <TodoTextInput
          id="new-todo"
          placeholder="What needs to be done?"
          onSave={this._onSave}
        />
      </header>
    );
  },
  _onSave: function(text) {
    if (text.trim()){
      TodoActions.create(text);
    }
  }

});

TodoTextInput.react.js

var TodoTextInput = React.createClass({

  getInitialState: function() {
    return {
      value: this.props.value || ''
    };
  },

  render: function() /*object*/ {
    return (
      <input
        className={this.props.className}
        id={this.props.id}
        placeholder={this.props.placeholder}
        onBlur={this._save}
        onChange={this._onChange}
        onKeyDown={this._onKeyDown}
        value={this.state.value}
        autoFocus={true}
      />
    );
  },

  _save: function() {
    this.props.onSave(this.state.value);
    this.setState({
      value: ''
    });
  },

  _onChange: function(/*object*/ event) {
    this.setState({
      value: event.target.value
    });
  },

  _onKeyDown: function(event) {
    if (event.keyCode === ENTER_KEY_CODE) {
      this._save();
    }
  }

});

Action 執行 Dispatcher 進行行爲分發,這裏的 Dispatcher 是 FB 實現的一個事情分發系統

TodoActions.js

var TodoActions = {
  create: function(text) {
    AppDispatcher.dispatch({
      actionType: TodoConstants.TODO_CREATE,
      text: text
    });
  },
  ...
}

Dispatcher 的分發會觸發 Store 中註冊的回調,執行對應的行爲更新數據,同時觸發 Store Change 事件,那麼 TodoApp.react.js 中監聽的 Store Change 事件就會觸發,從新設置組件的 state 數據,導致 View 從新 render

TodoStore.js

AppDispatcher.register(function(action) {
  var text;

  switch(action.actionType) {
    case TodoConstants.TODO_CREATE:
      text = action.text.trim();
      if (text !== '') {
        create(text);
        TodoStore.emitChange();
      }
      break;
    default:
      // no op
  }
});

這樣就造成了 Flux 架構的單向閉環更新流,可是寫起來仍是有些繁瑣和複雜性,下一節咱們來看更簡潔和優雅的方式 Redux ~

相關文章
相關標籤/搜索