如何将以下jQuery代码转换为React?

时间:2018-06-03 18:08:53

标签: javascript jquery reactjs api menu

我有以下代码,它基本上折叠了所有子菜单,只在点击时打开它们:

<ul class="menu">
  <li>
    <a href="#">One</a>
    <ul class="menu">
      <li>
        <a href="#">Alpha</a>
        <ul class="menu">
          <li><a href="#">Hello</a></li>
          <li><a href="#">World</a></li>
        ...
      <li><a href="#">Beta</a></li>
    </ul>
  </li>
  <li><a href="#">Three</a></li>
</ul>

<script type="text/javascript">
  $(".menu").children().click(function(e) {
    $(this).siblings().find("ul").hide();
    $(this).children().show();
  });
</script>

我已经使用递归函数创建了一个带有DRF子菜单API的菜单,并且已成功设法使用以下代码显示该API中的菜单:

class Recursive extends React.Component {
    render() {
        let childitems = null;

        if (this.props.children) {
            childitems = this.props.children.map(function(childitem) {
                return (
                    <Recursive item={childitem} children={childitem.children} />
                )
            })
        }
        return (
            <li key={this.props.item.id}>
                {this.props.item.name}
                { childitems ? <ul>{childitems}</ul> : null }
            </li>
        );
    }
}


class MenuDisplay extends React.Component {
    render() {
        let items = this.props.data.map(function(item) {
            return (
                <Recursive item={item} children={item.children} />
            )
        })
        return (
            <ul>
                {items}
            </ul>
        );
    }
}

如何在第一个示例中重构我的React代码以包含我用jQuery创建的函数?

这里是HTML的JSfiddle

3 个答案:

答案 0 :(得分:2)

您的递归菜单组件可以简化为单个组件,如下所示:

import React, { Component } from "react";

class Menu extends Component {
    state = {
        // initially no item is active
        active: null
    };

    // when clicked store the item id as active
    handleClick = id => this.setState({ active: id });

    render() {
        const { links } = this.props;
        const { active } = this.state;

        return (
            <ul className="menu">
                {links.map(({ id, name, children }) => (
                    <li key={id} onClick={() => this.handleClick(id)}>
                        {name}
                        {/* only render the children links when */}
                        {/* the item is the active one and the */}
                        {/* item actually has children */}
                        {id === active && children && (
                            <Menu links={children} />
                        )}
                    </li>
                ))}
            </ul>
        );
    }
}

并像这样使用它:

const LINKS = [
    {id: 'one', name: 'One', children: [
        {id: 'alpha', name: 'Alpha', children: [
            {id: 'hello', name: 'Hello'},
            {id: 'world', name: 'World'},
        ]},
        {id: 'beta', name: 'Beta'},
    ]},
    {id: 'two', name: 'Two'},
]

ReactDOM.render(<Menu links={LINKS} />, document.getElementById('root'));

查看有效示例以查看实际效果:

Edit jn6vqn5jzy

通过使每个递归菜单组件将活动链接存储为状态并仅为活动项呈现该链接的子代来实现jQuery功能。

请注意,您不必隐藏带有react的元素。如果不应该显示它们,则不要首先渲染它们。在此示例中,通过将活动ID与应呈现的项目ID进行比较来进行检查。如果匹配->渲染子链接。

答案 1 :(得分:1)

我在React中绘制了一个我认为你想要的实例,因为我今天没有生命也无所事事。)

简而言之,有几种方法可以做到这一点但是,我认为最好的方法是制作一个单独的反应组件,它将根据其状态选择显示或隐藏子组件。它可能看起来比你的jQuery解决方案更多的代码,但是,这可能解决一些渲染问题,这些问题可能来自隐藏和显示CSS的东西。无论如何,这里是fiddle link,我将粘贴下面的代码。

class Menu extends React.Component{
    constructor(props){
    super(props);
    this.state = {
        open: false
    }

    this.toggleDropDown = this.toggleDropDown.bind(this);
  }

  toggleDropDown(){
    // this toggles the open state of the menu
    this.setState({open: !this.state.open})
  }

  render(){
    // only display children if open is true
    return(
        <ul className="menu">
        <li onClick={this.toggleDropDown}>         {this.props.title}  </li>
        {(this.state.open)?this.props.children:null}
        </ul>
    )
  }
}

class Hello extends React.Component {
  render() {
    return (
    <div>
      <Menu title="one">
        <Menu title="Alpha">
          <ul>
            <li>Hello</li>
            <li>World</li>
          </ul>
        </Menu>
        <Menu title="Beta">
          <ul>
            <li>Hello</li>
            <li>World</li>
          </ul>
        </Menu>
      </Menu>  
      <Menu title="two">
      <ul>
        <li>Alpha</li>
        <li>Beta</li>
        </ul>
      </Menu>
      <ul className="menu">
      <li>three</li>
      <li>four</li>
      </ul>
    </div>
    );
  }
}

ReactDOM.render(
  <Hello name="World" />,
  document.getElementById('container')
);

答案 2 :(得分:0)

基于迈克尔·索伦森(Michael Sorensen)的代码,我提出了状态并修改了代码。运行结果与jQuery代码几乎相同,不同之处在于,如果单击“一个”,则只会显示直接的子代。我有点喜欢,所以我把它留在那里。该代码粘贴在下面。

function Menu(props) {
  return (
    <ul className="menu">
      <li onClick={props.onClick}> {props.title} </li>
      {props.open ? props.children : null}
    </ul>
  );
}

class Hello extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      open: Array(2).fill(false),
      open2: Array(2).fill(false)
    };

    this.toggleDropDown = this.toggleDropDown.bind(this);
    this.toggleDropDown2 = this.toggleDropDown2.bind(this);
  }

  toggleDropDown(i) {
    const open = Array(2).fill(false);
    this.setState({
      open: open.fill(true, i, i + 1),
      open2: Array(2).fill(false)
    });
  }
  toggleDropDown2(i) {
    const open2 = Array(2).fill(false);

    this.setState({ open2: open2.fill(true, i, i + 1) });
  }

  render() {
    return (
      <div>
        <Menu
          key="0"
          title="one"
          open={this.state.open[0]}
          onClick={() => this.toggleDropDown(0)}
        >
          <Menu
            key="2"
            title="Alpha"
            open={this.state.open2[0]}
            onClick={() => this.toggleDropDown2(0)}
          >
            <ul>
              <li>Hello</li>
              <li>World</li>
            </ul>
          </Menu>
          <Menu
            key="3"
            title="Beta"
            open={this.state.open2[1]}
            onClick={() => this.toggleDropDown2(1)}
          >
            <ul>
              <li>Hello</li>
              <li>World</li>
            </ul>
          </Menu>
        </Menu>
        <Menu
          key="1"
          title="two"
          open={this.state.open[1]}
          onClick={() => this.toggleDropDown(1)}
        >
          <ul>
            <li>Alpha</li>
            <li>Beta</li>
          </ul>
        </Menu>
        <ul className="menu">
          <li>three</li>
          <li>four</li>
        </ul>
      </div>
    );
  }
}

ReactDOM.render(<Hello name="World" />, document.getElementById("container"));