3

ミスリルは初めてですが、本当に好きになりたいです。数週間前、状態管理に React と Redux を使用してデモ アプリをコーディングしました。ライブラリを使用して 2 つを接続しましたが、すべて機能し、http://curiousercreative.com/demos/bankDemo/で確認できます。Mithril を読み、読んだ内容の多くを気に入った後、同じデモ アプリを Mithril + Redux に翻訳することにしましたが、Mithril にマウントされたコンポーネントを更新/再描画することができないため、Redux ストアを更新します。 (状態) が UI に反映されることはありません。私のアプリの js/app.js 行 ~144-162 から、Redux コールバックと 2 つの最上位 Mithril コンポーネントがマウントされ、状態が渡されます。

// redraws Mithril whenever an action is dispatched
    store.subscribe(function () {
      console.log('happening');
      m.redraw.strategy('all');
      m.redraw(true);
    });

// Render Mithril
    // content
    m.mount(
      document.getElementById('content'),
      m.component(App, store.getState())
    );

    // nav
    m.mount(
        document.getElementById('navContainer'),
        m.component(Nav, store.getState())
    );

http://curiousercreative.com/demos/bankDemo-mithril/でコンソールを開くと、新しいリンクをクリックするたびにログ エントリが表示されます (Redux ステート ストアを更新するハッシュが変更されます)。上記のコードでは、ログが発生するたびにミスリルの強制再描画が発生するはずですが、もちろん UI は変更されません。その動作を、上記の React デモ アプリと比較してください。アプリの js/components.js ファイルでは、2 つの最上位コンポーネントがこの状態オブジェクトを引数として受け取り、子コンポーネントに渡します。

  var App = {
    controller: function (args) {
      this.activePageId = args.activePageId;
      this.accounts = args.accounts;
      ...

  var Nav = {
    controller: function (args) {
      this.activePageId = args.activePageId;
      this.accounts = args.accounts;
      ...

ミスリルが再描画されないのはなぜですか?

4

1 に答える 1

3

問題は、getState()初期化時に一度だけ呼び出されるため、コンポーネントは常に同じ元の静的データ ストア スナップショットへの参照で再描画されることです。

最上位コンポーネントがマウントされると、それらのコントローラーが実行され、それらのビューがコンパイルおよびビルドされ、コントローラーおよび渡された引数にアクセスできます。コントローラーは初期化時に一度だけ実行されます。再描画がトリガーされると、ビュー関数が再実行されます。つまり、ネストされたコンポーネントには、ビューがアクセスできる新しい引数を渡すことができますが、マウントされた (最上位の) コンポーネントには引数がバインドされており、ビュー自体の子孫ではないため、独自のロジックを決定する必要があります。参照を更新しています。

コードを見ると、いくつかのアイデアが飛び出します。

mount でメソッドを (呼び出さずに)渡すことができます。Mithril は、getStateビューでのデータの入力と取得に関数を使用することを強く支持しています (単純なモデル管理のための内部ツールであるm.propで見られるように)。

var component = {
  view : function( ctrl, accessor ){
    return m( 'p', accessor().value )
  }
}

m.mount( document.body, m.component( component, store.getState ) )

動的セレクター属性は、属性マップではるかに読みやすくなる傾向があります。セレクタ文字列クラスを属性マップ クラスと組み合わせることができることに注意してください。コントローラーで宣言されたactivePage関数は関心の分離のように見えますが、ビューにはその特定のメソッドへのフックが必要なため、関数は明示的に className を生成するためのものであり、ロジックは非常に単純であるため、複雑さが大幅に軽減され、そのロジックをビューに直接配置することで読みやすさを向上させます。

m('div.page', {
  id    : args.id,
  class : args.id === args.activePageId ? 'active' : ''
}, /* ... */ )

仮想 DOM の子を配列で明示的にラップする必要がないことに注意してください。それらを順番に含めることができます。事実上、これは Mithril 仮想 DOM 構文では角括弧が冗長であることを意味します。

m( '.parent',
  m( '.child1' ),
  m( '.child2' )
) 
于 2015-11-16T13:29:02.783 に答える