Fluxモードの概要

8552 ワード

  • fluxの核心思想は中心化制御であり、すべての要求と変更はactionによってしか発行できず、dispatcherによって統一的に割り当てられる.メリットは、Viewが高度に簡潔であることです.あまり論理に関心を持つ必要はありません.入力されたデータに関心を持つ必要があります.センター化により、すべてのデータが制御され、問題が発生した場合にクエリーが容易になります.
  • fluxの欠点も明らかで、階層が多すぎて、冗長コードを繰り返し書く必要があります.
  • Flux_GitHubアドレス
  • Fluxアプリケーションには、次の4つのセクションがあります.
  • Dispatcher,処理動作配信,Store間の依存関係を維持する
  • .
  • Store、データの格納と処理に関するロジック
  • を担当する
  • Action,トリガDispatcher
  • View、ビュー、ユーザーインタフェース
  • の表示を担当
  • 上図から分かるように、Fluxの特徴は一方向データストリームである.
  • ユーザは、ビューレイヤにおいて、Dispatcher
  • にActionオブジェクトを開始する
  • DispatcherはActionを受信し、Storeに対応する変更を要求する
  • Storeは、対応する更新を行い、changeイベント
  • を発行する.
  • Viewは、changeイベントを受信すると、ページ
  • を更新する.

    簡易図示コントラストMVC
  • 基本MVCデータストリーム
  • 複雑なMVCデータストリーム
  • 基本的なFluxデータストリーム
  • 複雑なFluxデータストリーム
  • MVCモードに比べてFluxはアイコンと矢印を多く出したが,すべてのせん断ヘッドが一方向を指し,システム全体に閉ループを形成するという重要な違いがある.
    パターンの進化
  • FluxはMVCモデルの転覆というよりMVCモデルの革新です
  • の従来のMVCモードでは、ViewがModelを直接修正する方式が非常にストレートであり、小型ウェブアプリケーションに適しているが、1つのウェブアプリケーションに複数のModel、複数のViewが存在すると、ModelとViewの間の決定関係が混乱し、制御しにくくなり、このモードはModelとViewのコンポーネント化分割を阻害する可能性がある.
  • 上の2つの複雑なモードのコントラスト図を比較すると、MVCモードの本当の痛みは、ユーザのインタラクティブな動作に関連するaction抽象
  • が欠けていることにある.
  • コードレベルから言えば、fluxは一般的なevent dispatcherにほかならない.従来のMVCの各Viewコンポーネント内のcontrollerコード断片をより適切な場所に抽出して集中化管理を行い、開発体験から快適でさわやかで制御しやすい「一方向ストリーム」モードを実現することを目的とし、このスケジューリングモードの下で、事の変化ははっきりと予測できるようになった.

  • Fluxソースの概要
    "shut up and show me the code"
           Dispatcher    
    
    Dispatcherファイル初期化
    var invariant = require('invariant');
    export type DispatchToken = string;
    var _prefix = 'ID_';
    class Dispatcher<TPayload> {
      _callbacks: {[key: DispatchToken]: (payload: TPayload) => void};
      _isDispatching: boolean;
      _isHandled: {[key: DispatchToken]: boolean};
      _isPending: {[key: DispatchToken]: boolean};
      _lastID: number;
      _pendingPayload: TPayload;
    
      constructor() {
        this._callbacks = {};
        this._isDispatching = false;
        this._isHandled = {};
        this._isPending = {};
        this._lastID = 1;
      }
      register(callback: (payload: TPayload) => void): DispatchToken {
        var id = _prefix + this._lastID++;
        this._callbacks[id] = callback;
        return id;
      }
      ...
    }
    
  • コードは切り取られたもので、ここでは主にDispatchToken関数、接頭辞'ID_'を登録します.自己増加の++を加えて一意性を確保する(1つのstoreが複数のidに対応することも可能であるはず)
  • callbacksは、DispatchTokenと関数コールバックのDictionaryです.
  • isDispatchingは、現在のDispatcherがdispatch状態にあるかどうかを示します.
  • isHandledは、tokenによって関数が処理されたかどうかを検出します.
  • isPendingは、tokenによって関数がDispatcherにコミットされたかどうかを検出します.
  • lastIDは、最近Dispatcherの関数体のUniqueID、すなわちDispatchTokenが加えられたものである.
  • pendingPayload、呼び出し関数に渡すパラメータが必要です.


  • dispatchメソッド
    dispatch(payload: TPayload): void {
        invariant(
          !this._isDispatching,
          'Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch.'
        );
        this._startDispatching(payload);
        try {
            for(var id in this._callbacks) {
        if (this._isPending[id]) {
            continue;
        }
        this._invokeCallback(id);
    }} finally {
        this._stopDispatching();
    }}
    
    isDispatching(): boolean {
        return this._isDispatching;
    }
    
    _invokeCallback(id: DispatchToken): void {
        this._isPending[id] = true;
        this._callbacks[id](this._pendingPayload);
        this._isHandled[id] = true;
    }
    
    _startDispatching(payload: TPayload): void {
    for(var id in this._callbacks) {
        this._isPending[id] = false;
        this._isHandled[id] = false;
    }
    this._pendingPayload = payload;
    this._isDispatching = true;
    }
    
    _stopDispatching(): void {
        delete this._pendingPayload;
        this._isDispatching = false;
    }
    
  • は主に関数がpending状態にあるか否かを判断し、非pending状態のcallbackを通過するinvokeCallback実行、すべての実行が完了した後、stopDispatching回復状態.
  • _startDispatching関数の役割は、登録されているすべてのcallbackの状態をクリアし、Dispatcherの状態をマークしてdispatching
  • に入ることです.
  • _invokeCallback関数は簡単で、実際にcallbackを呼び出す前にステータスをpendingに設定し、実行が完了するとhandled
  • に設定します.

    waitForメソッド
      waitFor(ids: Array): void {
        invariant(
          this._isDispatching,
          'Dispatcher.waitFor(...): Must be invoked while dispatching.'
        );
        for (var ii = 0; ii < ids.length; ii++) {
          var id = ids[ii];
          if (this._isPending[id]) {
            invariant(
              this._isHandled[id],
              'Dispatcher.waitFor(...): Circular dependency detected while ' +
              'waiting for `%s`.',
              id
            );
            continue;
          }
          invariant(
            this._callbacks[id],
            'Dispatcher.waitFor(...): `%s` does not map to a registered callback.',
            id
          );
          this._invokeCallback(id);
        }
      }
    
  • は、dispatch法によるコールバックの遍歴が簡単で同期的であると簡単に考えられる.callbackの実行中にwaifForメソッドに遭遇すると、現在のcallbackの呼び出しが中断され、wairForメソッドは宣言された依存に基づいて遍歴順序を再決定し、すべての依存が実行されると、元の中止したcallbackが実行されます.
  • ps:次の言葉はレプリケーションから来ています(参考にしてください)
  • は、まず、現在Dispatching状態である必要があると判断するInvariantである.最初は分かりにくいですが、簡単に言えば、Dispatching状態でなければ、圧根に関数が実行されていないことを説明しますが、あなたは誰を待っていますか?
  • その後、この関数はDispatchTokenの配列から遍歴され、遍歴されたDispatchTokenがpending状態にある場合、一時的にスキップされる.
  • しかし、ここで必要なループ以来のチェックは、A関数以来BのToken、B関数がAのTokenに依存すると「デッドロック」になる場合を考えてみましょう.したがって,1つの関数依存オブジェクトがpendingにある場合,この関数が実行され始めたことを示すが,同時にhandled状態に入らなければ,その関数も詰まっていることを示す.
  • token対応callbackが存在するかどうかをチェックし、このtoken対応の関数を呼び出します.

  • ps:この中の一部の画像と説明は第三者から来たが、思い出せないのか.