我想用React(ES6)创建一个动态JQuery菜单。我遵循JQuery菜单示例(https://jqueryui.com/menu/),但其中的所有示例都是创建静态菜单。它没有解释如何更改菜单项,如更新标签或启用。另外,我不想最终在React中使用新的菜单实现。
我的菜单项有一个json数组,它假定嵌套级别。
class Employee(object):
def __init__(self, employee_name):
self.employee_name = employee_name
def ReturnName(self, employee_name):
self.employee_name = employee_name
return employee_name
def calculate_wage(self, hours):
self.hours = hours
return hours * 20.00
class PartTimeEmployee(Employee):
def calculate_wage(self, hours):
self.hours = hours
return hours * 12.00
ft_emp = Employee("Mike")
ft_emp_name = ft_emp.ReturnName("Mike")
pt_emp = PartTimeEmployee("Bill")
#pt_emp_name = pt_emp.ReturnName("Bill")
ft_pay = ft_emp.calculate_wage(40)
#pt_pay = pt_emp_name.calculate_wage(20)
print "Full time employee %s made $%d for the week." %(ft_emp_name, ft_pay)
#print "Part time employee %s made $%d for the week." %(pt_emp_name, pt_pay)
>>>
Full time employee Mike made $800 for the week.
我想直接在菜单中更新任何json项目的标签或显示。我需要避免手动DOM操作,因为这是一种容易出错的方法。
答案 0 :(得分: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进行一些小改动:&#34; ui-state-disabled&#34;而不是禁用: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);
在您的componentDidMount中添加此代码段,以便启动菜单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"
}]});
使用&#34; - &#34;作为标签,将在设计JQuery Menu 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();
}