2017-05-26 5 views
1

React(ES6)を使用して動的なJQueryメニューを作成したいとします。私はJQueryのメニュー例(https://jqueryui.com/menu/)に従っていますが、そこにあるすべての例は静的メニューを作成しています。ラベルの更新や有効化などのメニュー項目の変更方法については説明していません。また、私はReactで新しいメニューの実装を終わらせたくありません。反応する動的JQueryメニュー

私はメニュー項目のjson配列を持っています。これはネストされたレベルを前提としています。

let simple= [{ 
      disabled: true, 
      label: "Item1" 
     }, 
     { 
      label: "Item2" 
     }, 
     { 
      label: "-" 
     }, 
     { 
      label: "Item3" 
     }, 
     { 
      label: "Item4", 
      children: [ 
       { 
        label: "Sub Item1" 
       }, 
       { 
        label: "Sub Item2" 
       }, 
       { 
        label: "Sub Item3" 
       } 
      ] 
     }]; 

json項目のラベルまたは表示をメニューで直接更新する必要があります。私は手作業によるDOM操作を避ける必要があります。なぜなら、エラーが発生しやすいアプローチですからです。

答えて

1

リアクトのダイナミックな操作は、突然変異の能力では簡単です。まず、私はあなたがすでにこれをしなかった、あなたはjQueryのライブラリをインポートする必要があると思う

import $ from 'jquery'; 
import 'jquery-ui/ui/core'; 
import 'jquery-ui/ui/widgets/menu'; 

を必要とそして、あなたは以下のように反応する成分の中で、あなたのメニューを参照する必要があります。動的ライフサイクルは、反応状態(https://facebook.github.io/react/docs/state-and-lifecycle.html)として処理されます。たとえば、menuItemsなどの状態を使用してJSONオブジェクト/配列を管理します。位置が絶対値に設定されていることがわかります。これがなければ、あなたが望む動作でなければ、あなたのメニューはあなたの文書全体を拡大させます。

<ul ref="menu" style={{display: "none", position: "absolute"}}> 
    {this.state.menuItems.map(this.processMenuEntry.bind(this, 0))} 
</ul> 

processMenuEntryメソッドの実装は以下のとおりです。確かに、このメソッドを更新して、異なるJSON構造に一致させることができます。 classNameを無効にする代わりに "ui-state-disabled"に変更することをお勧めします。したがって、有効化/無効化のみではなく、スタイルをカスタマイズするオプションが増えます。以下のメソッドは、上のスニペットの最初の呼び出しと同様に、ゼロで始まるネストされたレベルを前提としています。また、子コンポーネントにキーを割り当てることを確認することが重要です。

processMenuEntry(level, entry, idx){ 
     let id= "menu"+ level+ "_"+ idx; 

     if(!entry.className){ 
      entry.className= ""; 
     } 

     let children= entry.children; 
     let child; 
     if(children && children.length){ 
      child= <li className= {entry.className} key= {id}><div>{entry.label}</div><ul>{children.map(this.processMenuEntry.bind(this, level+1))}</ul></li>; 
     }else{ 
      child= <li className= {entry.className} key= {id}><div>{entry.label}</div></li>; 
     } 

     return child; 
} 

あなたの方法は、あなたのHTML

でコンポーネントを反応
this.processMenuEntry= this.processMenuEntry.bind(this); 

の同じコンテキストを開始するためには、あなたのcomponentDidMountで、このコードスニペットを追加していますので、この呼び出しを作るためにあなたのコンストラクタで確認してくださいクリックハンドラに加えて、メニューAPIが機能します。

componentDidMount(){ 
     $(this.refs.menu).menu({ 
      select: function(event, ui) { 
       //do 
      } 
     }); 
} 

たとえば、メニューの2番目の項目を無効にする場合は、これを行うだけです。

simple[1].className= "ui-state-disabled"; 
this.setState({"menuItems": simple}); 

あなたにも全く異なるJSON配列を設定し、それ

this.setState({"menuItems": [{ 
    label: "Some new Item1" 
}]}); 

の使用の世話をします反応することができ、「 - 」のラベルは、あなたのメニューに区切りを追加するとJQueryメニューAPIが設計されています。

最後に、メニューの切り替えを扱うか、またはメニューを非表示にするときは、次のスニペットを見ることができます。確かに、あなたの仕事に基づいて修正することができます。私はアンカーをクリックすると、メニューを切り替えることを前提としています。ユーザーがメニューの外側をクリックしたかどうかのチェックは、メニューが表示されている場合にのみ追加されます。

<a href="https://stackoverflow.com" onClick={this.toggleMenu}>Test</a> 

componentWillUnmount(){ 
    this.stopMenuListeners(); 
} 

stopMenuListeners(){ 
    $(document).off("click.menuOutsideClicks"); 
} 

toggleMenu(event){ 
     let menu= $(this.refs.menu); 
     let visible= !menu.is(':visible'); 
     menu.slideToggle("fast"); 

     this.stopMenuListeners(); 
     if(visible){ 
      setTimeout(()=>{ 
       this._handler= $(document).on("click.menuOutsideClicks", (event)=>{ 
        if(!$(event.target).closest(menu).length){ 
         menu.slideUp('slow').hide(); 
         this.stopMenuListeners(); 
        } 
       }); 
      }); 
     } 

     event.stopPropagation(); 
     event.preventDefault(); 
} 
関連する問題