2016-07-27 9 views
3

これがなぜ機能しないのか正直にはわかりません。かなり標準的な操作であるようです。コンポーネントをマウントしておらず、エラーを投げておらず、その直後に関数を実行していません。すべてのcfg.AddToCart.vm.addToCart()コントローラーの内部でマウントが動作しない

cfg.AddToCart = { 
    vm: { 
    init() { 
     return; 
    }, 

    addToCart() { 
     let parent = document.getElementById('atc-error'); 
     let errEl = document.getElementById('atc-error-component'); 

     if(cfg.state.selections.SIZE) { 
      m.mount(errEl, null); 
     } else { 
      let component = new cfg.selectComponent(cfg.Options, cfg.optionsView); 
      m.mount(errEl, component); 

      cfg.util.toggleSlide(parent); 
     } 
    } 
    }, 

    controller() { 
    cfg.AddToCart.vm.init(); 
    } 
}; 

cfg.AddToCart.view = function() { 
    return <div id="add-to-cart-container"> 
    <div id="atc-error"> 
     <span>Select a size and add to cart again.</span> 
     <div id="atc-error-component"></div> 
    </div> 
    <div class="small-12 columns"> 
     <button class="large button alert" 
      onclick={() => { 
       this.vm.addToCart(); 
      }}> 
      Add To Cart 
     </button> 
    </div> 
    </div>; 
}; 

にhapping私たちは、アプリケーション全体でnew cfg.selectComponent(cfg.Options, cfg.optionsView)コンポーネントを複数回使用するので、それはそれでエラーではありません。 #atc-errordisplay:noneに設定されていますが、これも問題ではないようです。これはアプリケーション内の唯一の条件付きマウントではないので、私はちょっと困惑しています。このパターンにそれを変更することにより、勤務

答えて

3

あなたがミスリルの利益の多くを逃している、それは私を打つ、あなたのコードを構造化しましたやり方を見てから。特に:

  1. あなたの「VM」は、コントローラと区別がつかない場合は、そのため全体の個別のオブジェクトを作成し、管理する必要はありません。特に、ローカルコンポーネントの状態を制御するメソッドを使用している場合は、はコントローラのジョブであるです。コントローラは、オブジェクトをビューに公開します。これは、その範囲の 'vm'とみなす必要があります。モデル状態を保持する別のオブジェクトを持つことは、状態がコンポーネントインスタンスの外で関係がある場合に便利です。既にcfg.stateにこの状態があるので、このシナリオではvmは冗長です。
  2. ミスリルビューには、描画ごとに実際のDOM要素を公開するconfigメソッドがあります。ここで行うことができるので、ビュー要素への参照を格納する必要はありません。これは、仮想DOMライブラリを魅力的なものにする大きな要素の1つです。ビューは賢明で、ビュー固有のロジックを直接導入することができます。
  3. コンポーネントはビュー内から直接呼び出すことができ、ビューは条件付きロジックを使用してそれらを呼び出すかどうかを判断できます。 m.mountは、ミスリルアプリケーションを初期化し、「トップレベル」のコンポーネントを定義するためにのみ必要です。 Mithrilコード内からは、m関数を介して直接ネストされたコンポーネントを呼び出すことができます。

他の誤解のカップル:

  1. コントローラは、ビューがレンダリングされる(そして、それが実行されますと、プロパティそれを初期化は、最初の引数としてビュー関数にさらされている)前に実行し、コントローラが初期化するときに、ビューで作成された要素にアクセスすることはできません。
  2. vminitの機能は意味を持ちません。

これは、上記を考慮したコードの書き換えです。コンパイルを避けるためにMSXの代わりにプレーンなミスリルを使用しましたが、簡単に元に戻すことができます:

// Determine what your external dependencies are 
const { state, selectComponent } = cfg 

// Define the component 
const AddToCart = { 
    // No need for a separate VM: it is identical in purpose & function to the controller 
    controller : function(){ 
    // No need to store element references in the model: those are the view's concern. 
    // Keep the VM/ctrl size to a minimum by only using it to deal with state 
    this.addToCart =() => { 
     if(state.selections.SIZE) 
     this.showSize = false 

     else { 
     this.showSize = true 

     this.slideToErr = true 
     } 
    } 
    }, 

    view : ctrl => 
    m('#add-to-cart-container', 
     m('#atc-error', { 
     // Config exposes the element and runs after every draw. 
     config : el => { 
      // Observe state, and affect the view accordingly: 
      if(ctrl.slideToErr){ 
      el.scrollIntoView() 

      // Reset the state flag 
      ctrl.slideToErr = false 
      } 
     } 
     }, 
     m('span', 'Select a size and add to cart again.'), 

     // This is an and condition, ie 'if A, then B 
      ctrl.showSize 
      // This is how you invoke a component from within a view 
     && m(selectComponent) 
    ), 

     m('.small-12 columns', 
     m('button.large button alert', { 
      onclick :() => 
      ctrl.addToCart(); 
     }, 
      'Add To Cart' 
     ) 
    ) 
    ) 
} 
+0

ありがとうございました。私たちは実際にコンポーネントを作るいくつかの方法を持っていて、私は古いポストからこのスタイルを見つけたかもしれません。我々は、それらを設定するより正しい方法がどんなものだろうと思っています。私はこれを非常に詳しく見ていきます! –

0

cfg.AddToCart = { 
    vm: { 
    init() { 
     this.errorComponent = m.prop(); 
    }, 

    addToCart() { 
     let parent = document.getElementById('atc-error'); 
     let errEl = document.getElementById('atc-error-component'); 

     if(cfg.state.selections.SIZE) { 
      cfg.util.toggleSlide(parent); 
      setTimeout(() => { 
       this.errorComponent(null); 
      }, 400); 
     } else { 
      let component = new cfg.selectComponent(cfg.Options, cfg.optionsView); 
      this.errorComponent(component); 

      setTimeout(() => { 
       cfg.util.toggleSlide(parent); 
      }, 100); 
     } 
    } 
    }, 

    controller() { 
    cfg.AddToCart.vm.init(); 
    } 
}; 

cfg.AddToCart.view = function() { 
    return <div id="add-to-cart-container"> 
    <div id="atc-error"> 
     <span>Select a size and add to cart again.</span> 
     <div id="atc-error-component" class="row"> 
      {this.vm.errorComponent() ? m.component(this.vm.errorComponent()) : ''} 
     </div> 
    </div> 
    <div class="small-12 columns"> 
     <button class="large button alert" 
      onclick={() => { 
       this.vm.addToCart(); 
      }}> 
      Add To Cart 
     </button> 
    </div> 
    </div>; 
}; 
関連する問題