动态JQuery菜单有反应

时间:2017-05-26 19:58:29

标签: javascript jquery html json reactjs

我想用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操作,因为这是一种容易出错的方法。

1 个答案:

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