Как создать блок-схему иерархии меню в ReactJS или HTML / CSS

#javascript #html #css #reactjs

#javascript #HTML #css #reactjs

Вопрос:

Дизайн Figma

Привет, я работаю над побочным проектом, в котором я хочу разработать компонент react, который может отображать детали на верхней панели с текстом и двумя кнопками, а внизу — иерархию, стилизованную под блок-схему меню. каждый пункт меню будет расширяться при нажатии на знак плюс и сворачиваться при нажатии на знак минус.

Я новичок в reactjs, я не знаю, как отображать такие компоненты, можете ли вы мне здесь помочь?

Если у вас есть какие-либо вопросы, пожалуйста, прокомментируйте ниже и заранее спасибо.

Комментарии:

1. Что-нибудь, что вы пробовали на данный момент?

2. Да, это не одно и то же, и есть много ограничений. material-ui.com/components/tree-view

3. Можете ли вы предоставить какой-нибудь образец объекта, с помощью которого вы хотите отобразить эту иерархию блок-схемы

Ответ №1:

Вы могли бы использовать рекурсивный подход, при котором вы отображаете дочерние (вложенные) элементы внутри компонента с помощью map метода, если есть дочернее свойство и isOpen значение true .

Структура данных представляет собой массив объектов, в котором каждый объект имеет title , text и children свойство, которое представляет собой массив той же структуры. Это будет работать с данными любого уровня глубины.

 const data = [{"title":"item-1","text":"Lorem ipsum dolor sit amet.","children":[{"title":"item-1-1","text":"Lorem ipsum dolor sit amet.","children":[{"title":"item-1-1-1","text":"Lorem ipsum dolor sit amet."},{"title":"item-1-1-2","text":"Lorem ipsum dolor sit amet."}]},{"title":"item-1-2","text":"Lorem ipsum dolor sit amet."}]},{"title":"Item 2","text":"Lorem ipsum dolor sit amet.","children":[{"title":"Item 4","text":"Lorem ipsum dolor sit amet."}]}]

const { useState } = React;

const App = ({ items }) => (
  items.map((item, i) => (
    <Item {...item} key={i}/>
  ))
)

const ItemHeader = ({ title, isOpen, setIsOpen }) => (
  <div className="item-header">
    <span>{title}</span>
    <button onClick={() => setIsOpen(!isOpen)}>{isOpen ? '-' : ' '}</button>
  </div>
)

const ItemBody = ({ text, children, isOpen }) => (
  <div className={`item-body ${isOpen ? 'show' : 'hide'}`}>
    <p>{text}</p>
  </div>
)

const Item = ({ title, text, children }) => {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div className="item">
      <div class="item-content">
        <ItemHeader
          title={title}
          isOpen={isOpen}
          setIsOpen={setIsOpen}/>

        <ItemBody
          isOpen={isOpen}
          text={text}
          children={children}/>
      </div>

      <div class="item-children">
        {children amp;amp; isOpen amp;amp; children.map((item, i) => <Item {...item} key={i}/>)}
      </div>
    </div>
  )
}

ReactDOM.render(
  <App items={data}/>,
  document.querySelector('#root')
) 
 .item {
  color: white;
  font-size: 14px;
  margin-bottom: 10px;
}

.item-content {
  padding: 5px 10px;
  border-radius: 5px;
  background: #252525;
  margin-bottom: 10px;
}

.item-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.item-header button {
  cursor: pointer;
}

.item-body {
  display: flex;
  flex-direction: column;
}

.hide {
  display: none;
}

p {
  margin: 5px 0
}

.item-children {
  margin-left: 10px;
} 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div> 

Комментарии:

1. Большое спасибо за ответ. Я уже создал аналогичные функции, основная проблема, с которой я сталкиваюсь, — это подключение каждого компонента с помощью строк, что-то вроде сообщений в Твиттере. как я могу добиться таких функций.

Ответ №2:

Отказ от ответственности. Когда люди спрашивают в комментариях «что вы пробовали до сих пор?», Они, кроме как помочь вам решить какую-то проблему, а не «сделать это за вас». Обязательно попробуйте что-нибудь, прежде чем слепо спрашивать.

Для ее создания вам не нужны библиотеки (из вашей текущей версии вопроса). Все, что вам нужно сделать, это реализовать составной шаблон компонента. Очень простой пример:

 export class FlowItem extends React.Component {

   render() {
      const {header, children} = this.props;

      return (
         <div>
             Ping from {header}
             <div style={{marginLeft: '20px'}}>
                 {children}
             <div/>

         <div/>
      );
   }
}
 

И это пример использования ниже.

 export class Content extends React.Component {

   render() {

      return (
         <div
            <FlowItem 
              header={"Very Top 1"}>
                  <FlowItem 
                     header={"Parent 1"}>
                  <FlowItem/>
            <FlowItem/>


            <FlowItem 
              header={"Very Top 2"}>
                  <FlowItem 
                     header={"Parent 1"}>
                  <FlowItem/>

                  <FlowItem 
                     header={"Parent 2"}>
                      <FlowItem header={"Child 1"}/>
                      <FlowItem header={"Child 2"}/>
                  <FlowItem/>

                  <FlowItem 
                     header={"Parent 3"}>
                  <FlowItem/>
            <FlowItem/>

         <div/>
      );
   }
}
 

Еще один простой пример, если вы хотите использовать с реальными объектами в массиве. Я думаю, что это ваш случай из вопроса:

 export class Content extends React.Component {

   render() {

      const root = {
       header: "Root 1",
       children: [
       {
        header: "Parent 1",
        children: [
         {
           header: "Child 1",
           children: [
            {
              header: "Inner 1",
              children: null
            }
           ]
         },
         {
           header: "Child 2",
           children: null
         }, 
         {
           header: "Child 3",
           children: null
         }
        ]
       },

       {
        header: "Parent 2",
        children: [
         {
           header: "Child 1",
           children: null
         },
         {
           header: "Child 2",
           children: null
         }
        ]
       },
      ]};

      return (
         <div>
            {this.getItemView(root)}
         <div/>
      );
   }

   getItemView = (node) => {
        return (
           <FlowItem 
             header={node.header}>
             {node.children ?
                node.children.map((obj, idx) => {
                  
                return (this.getItemView(obj));
           
             }) : <div/>}
           <FlowItem/>
        );
   };
}
 

Ответ №3:

Это также возможно с помощью ЧИСТОГО CSS и JS, проверьте это и расширяйте по мере необходимости.

Пример меню Mutilevel в W3School