Вложенное меню боковой панели с пользовательским интерфейсом материала и Reactjs - PullRequest
0 голосов
/ 07 августа 2020

Я пытаюсь разработать меню боковой панели с использованием пользовательского интерфейса материала. Я могу сделать это для простого списка. В моем проекте у меня есть требование о вложенном меню боковой панели, чего я не могу достичь. Если я пытаюсь использовать рекурсивную функцию, она предоставляет только главное меню заголовка и не отображает дочерние элементы. Пожалуйста, помогите мне разработать его.

Код для вложенного меню боковой панели, как показано ниже,

import React, {useState} from 'react';
import { makeStyles } from '@material-ui/core/styles';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import Collapse from '@material-ui/core/Collapse';
import ExpandLess from '@material-ui/icons/ExpandLess';
import ExpandMore from '@material-ui/icons/ExpandMore';

const useStyles = makeStyles((theme) => ({
  root: {
    width: '100%',
    maxWidth: 360,
    backgroundColor: theme.palette.background.paper,
  },
  nested: {
    paddingLeft: theme.spacing(4),
  },
}));

export const Menu = ({items}) => {
  const classes = useStyles();
  const [open, setOpen] = useState(true);

  const handleClick = () => {
    setOpen(!open);
  };

  return (
    items.map(item =>
      !item.children ? (
          <div key={item.title}>
            <ListItem button>
              <ListItemIcon>
                {item.icon}
              </ListItemIcon>
              <ListItemText primary={item.title} />
            </ListItem>
          </div>
        ) : (
          <div
            component="nav"
            key={item.title}
          >
            <ListItem button onClick={handleClick}>
              <ListItemIcon>
                {item.icon}
              </ListItemIcon>
              <ListItemText primary={item.title} />
              {open ? <ExpandLess /> : <ExpandMore />}
            </ListItem>
            <Collapse in={open} timeout="auto" unmountOnExit>
              <List component="div" disablePadding>
                <ListItem button className={classes.nested}>
                  <ListItemIcon>
                    {item.icon}
                  </ListItemIcon>
                  <ListItemText>
                    <Menu items={item} />
                  </ListItemText>
                </ListItem>
              </List>
            </Collapse>
          </div>
        )
    )
  );
}

код пункта меню здесь,

import HomeOutlinedIcon from "@material-ui/icons/HomeOutlined";
import LocalLibraryOutlinedIcon from "@material-ui/icons/LocalLibraryOutlined";
import TrendingUpOutlinedIcon from "@material-ui/icons/TrendingUpOutlined";
import DescriptionOutlinedIcon from "@material-ui/icons/DescriptionOutlined";
import React from "react";


export const menu = [
  {
    icon: <HomeOutlinedIcon/>,
    title: 'Home',
    items: []
  },
  {
    icon: <LocalLibraryOutlinedIcon/>,
    title: 'Education',
    items: [
      {
        title:'Technical Analysis',
        items: [
          {
            title: 'The Dow Theory',
            to: '/thedowtheory'
          },
          {
            title: 'Charts & Chart Patterns',
            to: '/chart'
          },
          {
            title: 'Trend & Trend Lines',
            to: '/trendlines'
          },
          {
            title: 'Support & Resistance',
            to: '/sandr'
          },
        ]
      },
      {
        title:'Fundamental Analysis',
        items: [
          {
            title: 'The Dow Theory',
            to: '/thedowtheory'
          },
          {
            title: 'Charts & Chart Patterns',
            to: '/chart'
          },
          {
            title: 'Trend & Trend Lines',
            to: '/trendlines'
          },
          {
            title: 'Support & Resistance',
            to: '/sandr'
          },
        ]
      },
      {
        title:'Elliot Wave Analysis',
        items: [
          {
            title: 'The Dow Theory',
            to: '/thedowtheory'
          },
          {
            title: 'Charts & Chart Patterns',
            to: '/chart'
          },
          {
            title: 'Trend & Trend Lines',
            to: '/trendlines'
          },
          {
            title: 'Support & Resistance',
            to: '/sandr'
          },
        ]
      },
      ]
  },
  {
    icon: <TrendingUpOutlinedIcon/>,
    title: 'Options'
  },
  {
    icon: <DescriptionOutlinedIcon/>,
    title: 'Blog'
  },
]

Ответы [ 2 ]

2 голосов
/ 07 августа 2020

Во-первых, у вас опечатка. Вы зацикливаетесь на клавише children вместо items. Но даже если вы это исправите, ваш код все равно не будет работать так, как вы хотите.

Я бы упростил свой подход, создав повторно используемые компоненты SingleLevel и MultiLevel для обработки текущего пункта меню. Если текущий элемент имеет children / items, то я бы использовал компонент MultiLevel else SingleLevel.

SingleLevel Component

const SingleLevel = ({ item }) => {
  return (
    <ListItem button>
      <ListItemIcon>{item.icon}</ListItemIcon>
      <ListItemText primary={item.title} />
    </ListItem>
  );
};

Многоуровневый компонент

const MultiLevel = ({ item }) => {
  const { items: children } = item;
  const [open, setOpen] = useState(false);

  const handleClick = () => {
    setOpen((prev) => !prev);
  };

  return (
    <React.Fragment>
      <ListItem button onClick={handleClick}>
        <ListItemIcon>{item.icon}</ListItemIcon>
        <ListItemText primary={item.title} />
        {open ? <ExpandLessIcon /> : <ExpandMoreIcon />}
      </ListItem>
      <Collapse in={open} timeout="auto" unmountOnExit>
        <List component="div" disablePadding>
          {children.map((child, key) => (
            <MenuItem key={key} item={child} />
          ))}
        </List>
      </Collapse>
    </React.Fragment>
  );
};

Чтобы определить, какой компонент использовать, я бы затем создал вспомогательную функцию hasChildren, которая возвращает true, если текущий элемент соответствует всем моим определенным условиям, которые необходимо учитывать. как родительский пункт меню.

utils. js

export function hasChildren(item) {
  const { items: children } = item;

  if (children === undefined) {
    return false;
  }

  if (children.constructor !== Array) {
    return false;
  }

  if (children.length === 0) {
    return false;
  }

  return true;
}

Я бы затем абстрагировал все это на другом MenuItem компоненте.

Компонент MenuItem

const MenuItem = ({ item }) => {
  const Component = hasChildren(item) ? MultiLevel : SingleLevel;
  return <Component item={item} />;
};

И, наконец, вот как я oop элементы menu

export default function App() {
  return menu.map((item, key) => <MenuItem key={key} item={item} />);
}

Редактировать lucid-lichterman-s5uhm

1 голос
/ 07 августа 2020

image {открыто ? : } ); }; экспортировать функцию по умолчанию Menu ({items}) {const createList = (items) => {let menu = []; items.map ((menuItem) => {if (Array.isArray (menuItem.items) && menuItem.items.length> 0) {menu.pu sh ( ); } else {menu.pu sh ( ); }}); возвратите menu.concat (); }; возврат {createList (items)} ; }

индекс. js (Использование):

import React from "react";
import ReactDOM from "react-dom";
import Demo from "./demo";
import HomeOutlinedIcon from "@material-ui/icons/HomeOutlined";
import LocalLibraryOutlinedIcon from "@material-ui/icons/LocalLibraryOutlined";
import TrendingUpOutlinedIcon from "@material-ui/icons/TrendingUpOutlined";
import DescriptionOutlinedIcon from "@material-ui/icons/DescriptionOutlined";

export const menu = [
  {
    icon: <HomeOutlinedIcon />,
    title: "Home",
    items: []
  },
  {
    icon: <LocalLibraryOutlinedIcon />,
    title: "Education",
    items: [
      {
        title: "Technical Analysis",
        items: [
          {
            title: "The Dow Theory",
            to: "/thedowtheory"
          },
          {
            title: "Charts & Chart Patterns",
            to: "/chart"
          },
          {
            title: "Trend & Trend Lines",
            to: "/trendlines"
          },
          {
            title: "Support & Resistance",
            to: "/sandr"
          }
        ]
      },
      {
        title: "Fundamental Analysis",
        items: [
          {
            title: "The Dow Theory1",
            to: "/thedowtheory"
          },
          {
            title: "Charts & Chart Patterns",
            to: "/chart"
          },
          {
            title: "Trend & Trend Lines",
            to: "/trendlines"
          },
          {
            title: "Support & Resistance",
            to: "/sandr"
          }
        ]
      },
      {
        title: "Elliot Wave Analysis",
        items: [
          {
            title: "The Dow Theory",
            to: "/thedowtheory"
          },
          {
            title: "Charts & Chart Patterns",
            to: "/chart"
          },
          {
            title: "Trend & Trend Lines",
            to: "/trendlines"
          },
          {
            title: "Support & Resistance",
            to: "/sandr"
          }
        ]
      }
    ]
  },
  {
    icon: <TrendingUpOutlinedIcon />,
    title: "Options"
  },
  {
    icon: <DescriptionOutlinedIcon />,
    title: "Blog"
  }
];
ReactDOM.render(<Demo items={menu} />, document.querySelector("#root"));

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...