【问题标题】:React nested menu. How to build dynamic nested menu from json反应嵌套菜单。如何从 json 构建动态嵌套菜单
【发布时间】:2020-11-27 11:57:02
【问题描述】:

我正在从 .json 制作侧边栏菜单。菜单项是 BMW 车型。 示例数据如下

我的回报:

<List>
      {Menuhandler( menuDataHandler(JsonSeries) )}
</List>

MenuDataHandler 使 json 变成这种格式

    let seriesData =  {
                "name": 1-series,
                "url" : /1-series,
                "children" : [ 
                    {
                    "name": e82,
                    "url" : /1-series/e82,
                     {
                    "name": e87,
                    "url" : /1-series/e87
                    }
                    }
                  ]}, {
                "name": 2-series,
                "url" : /2-series,
                "children" : [ 
                    {
                    "name": e82,
                    "url" : /2-series/e82
                    },{
                    "name": e87,
                    "url" : /2-series/e87
                    }
                  ]},
                {
                "name": 3-series,
                "url" : /3-series,
                "children" : [ 
                    {
                    "name": e82,
                    "url" : /3-series/e82
                    }, {
                    "name": e87,
                    "url" : /3-series/e87
                    }
                  ]},
                    {
                "name": 4-series,
                "url" : /4-series,
                "children" : [ 
                    {
                    "name": e82,
                    "url" : /4-series/e82
                    },
                   {
                    "name": e87,
                    "url" : /4-series/e87
                    }
                  ]}

Menuhandler 是这样构建的。

const Menuhandler = ( menulist ) => { 

return menulist.map( ( oneMenuItem, i ) => {

  //console.log( oneMenuItem.index)
    /* 
    If oneMenuitem does not have children return listitem to go wanted url. 
    */
      if (!oneMenuItem.children) {
        return (
          <div key={i}>
         <ThemeProvider theme={theme}>
    
            <ListItem button>
              <Link to={ oneMenuItem.url } className="dropdown-link">
                <ListItemText inset primary={ oneMenuItem.name }/>
              </Link>
            </ListItem>
          </ThemeProvider>
          </div>
        )
      }
      /*
      If oneMenuItem have children. Return Listitem and Collapse. Inside 
     Collapse call {Menuhandler(oneMenuItem.children)} so inside Collapse 
     will be children. This is Loop will go until there is no childrens and 
     it will return above ListItem
      */

      return (
        <div key={i}>
        <ThemeProvider theme={theme}>
          <div className="dropdownItem">
            <ListItem
              button
              key={oneMenuItem.index}
              onClick={() => handleClick(oneMenuItem.url)}
            >
              <Link to={oneMenuItem.url} className="dropdown-link">
                <ListItemText inset primary={oneMenuItem.name} />
              </Link>
              
              { open[ oneMenuItem.url ] ? 
                    <ExpandLess /> :
                    <ExpandMore />
                  } 
              
            </ListItem>
            <div className="menubar-handler">
            </div>

            <Collapse
              in={open[oneMenuItem.url]}
              unmountOnExit
              className="childrenItem"
            >
              {Menuhandler(oneMenuItem.children)}
            </Collapse>
          </div>
        </ThemeProvider>
        </div>
      );
    });
  };

手柄点击

const handleClick = ( ComingUrl ) => {
  //console.log(ComingUrl)
  setOpen( prevState => ( {...open, [ ComingUrl ]: !prevState[ ComingUrl ] } ) )
}

现在有趣的部分来了。 Collapse 现在在一种状态下工作。 打开[oneMenuItem.url]。 HandleClick 只会打开一个对象。在那里它将添加 item : value。

*click* {/1-series:true}.
*next click* {/1-series:true, /2-series: true}. 

现在有两个折叠打开了。如果我再次单击同一项目,它将使 value 为 false,反之亦然。然后一个折叠关闭。

我想让 HandleClick 在同级项目中自动关闭。

所以如果打开有:

{/1-series:true, /2-series: true, /3-series: true,/4-series: true}

这不可能发生。我希望它是怎样的。

 // one scenario
{/1-series:true, /2-series: false, /3-series: false,/4-series: false}
// Second one 
{/1-series:false, /2-series: true, /3-series: false,/4-series: false}

在儿童级别也是如此。 如果 /1-series/e82 为真 /1-series/e87 将为假。

【问题讨论】:

    标签: arrays reactjs material-ui


    【解决方案1】:

    如果我对您的问题的理解正确,您有一个可以点击的项目列表。单击一个项目将其展开以显示更多数据。一次只能展开一项。假设这是正确的,这里有一种方法:

    如果一次只能打开一个项目,为什么不对组件状态进行建模,以便只指定打开的项目?这样,您只需要跟踪您的状态的单个值。

    这是下面示例的codesandbox

    function MenuItem({ open, name, onClick, children }) {
      return <li onClick={() => onClick(name)}>{open ? children : name}</li>;
    }
    
    function Menu() {
      const [openItem, setOpenItem] = React.useState(null);
      return (
        <ul>
          <MenuItem open={openItem === "foo"} onClick={setOpenItem} name="foo">
            open foo
          </MenuItem>
          <MenuItem open={openItem === "bar"} onClick={setOpenItem} name="bar">
            open bar
          </MenuItem>
          <MenuItem open={openItem === "baz"} onClick={setOpenItem} name="baz">
            open baz
          </MenuItem>
        </ul>
      );
    }
    

    【讨论】:

    • 嘿!谢谢你的评论!这实际上是一个非常好的主意!我是编码方面的新手。我看过许多其他嵌套菜单,但没有一个能满足我的需要。我认为我们应该制作一个任何人都可以使用的产品。
    猜你喜欢
    • 2010-11-04
    • 2019-02-24
    • 2013-02-25
    • 2012-12-22
    • 2014-07-17
    • 1970-01-01
    • 2016-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多