带有反应的动态 JQuery 菜单



我想用 React (ES6) 创建一个动态的 JQuery 菜单。我正在遵循 JQuery 菜单示例 (https://jqueryui.com/menu/),但其中的所有示例都在创建静态菜单。它不解释如何更改菜单项,例如更新标签或启用。另外,我不想在 React 中以菜单的新实现结束。

我的菜单项有一个 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 操作,因为它是一种容易出错的方法。

React 中的动态操作具有突变功能非常简单。首先,我认为您已经这样做了,您需要导入所需的 JQuery 库

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

您需要在 react 组件中引用您的菜单,如下所示。动态生命周期将作为反应状态 (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 中具有与 react 组件相同的上下文

this.processMenuEntry= this.processMenuEntry.bind(this);

在组件DidMount中添加此代码片段,以便启动菜单API工作,以及单击处理程序。

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

现在,例如,如果您想禁用菜单中的第二项,您可以简单地这样做。

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

你也可以设置一个完全不同的 JSON 数组,React 会处理它。

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

最新更新