2017-05-26 67 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

React中的動態操作對於突變功能來說很簡單。首先,我想你已經這樣做,你需要導入的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」而不是disabled:true。因此,您將有更多選項來自定義您的樣式,而不僅僅是啓用/禁用。下面的方法假定嵌套級別,以零開頭,就像上面代碼片段中的初始調用一樣。確保爲子組件分配密鑰很重要。

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 
      } 
     }); 
} 

現在,例如,如果要禁用菜單中的第二項,則可以簡單地執行該操作。

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(); 
}