如何制作嵌套的手风琴?

时间:2017-12-21 14:17:36

标签: javascript reactjs semantic-ui semantic-ui-react

在semantic_ui-react库中存在组件Accordion。有一些例子,但我必须制作嵌套的手风琴,它有结构:

-accordion:
    -sub_accordion1
    -sub_accordion2
    -sub_accordion3

我看到有嵌套式手风琴与面板的例子,但我不想把手风琴放在面板上。我试过了:

export default class AccordionExampleStandard extends Component {
  state = { activeIndex: 0 }

  handleClick = (e, titleProps) => {
    const { index } = titleProps
    const { activeIndex } = this.state
    const newIndex = activeIndex === index ? -1 : index

    this.setState({ activeIndex: newIndex })
  }

  render() {
    const { activeIndex } = this.state

    return (
      <Accordion>
        <Accordion.Title active={activeIndex === 0} index={0} onClick={this.handleClick}>
          <Icon name='dropdown' />
          What is a dog?
        </Accordion.Title>
        <Accordion.Content active={activeIndex === 0}>
          <Accordion.Title active={activeIndex === 1} index={1} onClick={this.handleClick}>
          <Icon name='dropdown' />
          What kinds of dogs are there?
        </Accordion.Title>
        <Accordion.Content active={activeIndex === 1}>
          Content1
        </Accordion.Content>

        <Accordion.Title active={activeIndex === 2} index={2} onClick={this.handleClick}>
          <Icon name='dropdown' />
          How do you acquire a dog?
        </Accordion.Title>
        <Accordion.Content active={activeIndex === 2}>
          Content2
        </Accordion.Content>
<Accordion.Title active={activeIndex === 3} index={3} onClick={this.handleClick}>
          <Icon name='dropdown' />
          What kinds of dogs are there?
        </Accordion.Title>
        <Accordion.Content active={activeIndex === 3}>
         Content3
        </Accordion.Content>
        </Accordion.Content>
      </Accordion>
    )
  }
}

它呈现组件,但我只能折叠主手风琴,不能折叠它的孩子。我该如何执行此功能?

3 个答案:

答案 0 :(得分:1)

这是我的版本。它是 Accordion 内 Accordion 内的递归 Accordion(无限)。

它也在 CodePen https://codepen.io/codeman1293/pen/OJWppQM?editors=1111

console.clear();
const ButtonToolbar = ReactBootstrap.ButtonToolbar;
const Button = ReactBootstrap.Button;
const Jumbotron = ReactBootstrap.Jumbotron;
const Accordion = ReactBootstrap.Accordion;
const Panel = ReactBootstrap.Panel;

var baseItems = [
  { id: 1, title: "Land", body: "", parentId: 0 },
  { id: 2, title: "Sea", body: "Submarine", parentId: 0 },
  {
    id: 8,
    title: "Air",
    body: "Helicopter<br />Aeroplanes<br />Drones",
    parentId: 0
  },
  { id: 3, title: "Cars", body: "", parentId: 1 },
  { id: 4, title: "Vans", body: "Transit<br />Sprinter", parentId: 1 },
  {
    id: 5,
    title: "Boats",
    body: "Speedboat<br />Fishing Boat<br />Dinghy",
    parentId: 2
  },
  { id: 6, title: "Petrol", body: "", parentId: 3 },
  { id: 7, title: "Automatic", body: "", parentId: 6 },
  { id: 9, title: "2.0L", body: "BMW X3<br />Mercedes GLC<br />Audi Q5", parentId: 7 }
];

const App = React.createClass({
  render() {
    const RecursiveAccordion = ({ items, recurse = false }) => {
      return (
        <Accordion>
          {items.map((item, index) => {
            var children = baseItems.filter((i) => {
              return i.parentId === item.id;
            });

            var hasChildren = children.length > 0;

            if (item.parentId === 0) {
              return (
                <Panel header={item.title} eventKey={index}>
                  {hasChildren && (
                    <div>
                      <RecursiveAccordion items={children} recurse={true} />
                      <div dangerouslySetInnerHTML={{ __html: item.body }} />
                    </div>
                  )}
                  {!hasChildren && (
                    <div dangerouslySetInnerHTML={{ __html: item.body }} />
                  )}
                </Panel>
              );
            }

            if (recurse) {
              return (
                <Panel header={item.title} eventKey={index}>
                  {hasChildren && (
                    <div>
                      <RecursiveAccordion items={children} recurse={true} />
                      <div dangerouslySetInnerHTML={{ __html: item.body }} />
                    </div>
                  )}
                  {!hasChildren && (
                    <div dangerouslySetInnerHTML={{ __html: item.body }} />
                  )}
                </Panel>
              );
            }
          })}
        </Accordion>
      );
    };

    return <RecursiveAccordion items={baseItems} recurse={false} />;
  }
});

ReactDOM.render(<App />, document.getElementById("app"));

答案 1 :(得分:0)

制作嵌套手风琴的正确方法:

import React from 'react'
import { Accordion } from 'semantic-ui-react'

const level1Panels = [
  { title: 'Level 1A', content: 'Level 1A Contents' },
  { title: 'Level 1B', content: 'Level 1B Contents' },
]

const Level1Content = (
  <div>
    Welcome to level 1
    <Accordion.Accordion panels={level1Panels} />
  </div>
)

const level2Panels = [
  { title: 'Level 2A', content: 'Level 2A Contents' },
  { title: 'Level 2B', content: 'Level 2B Contents' },
]

const Level2Content = (
  <div>
    Welcome to level 2
    <Accordion.Accordion panels={level2Panels} />
  </div>
)

const rootPanels = [
  { title: 'Level 1', content: { content: Level1Content, key: 'content-1' } },
  { title: 'Level 2', content: { content: Level2Content, key: 'content-2'         } },
]

const AccordionExampleNested = () => (
  <Accordion defaultActiveIndex={0} panels={rootPanels} styled />
)

export default AccordionExampleNested

答案 2 :(得分:0)

由于您提到需要一个简单的解决方案,因此最好使用panels,因为它们似乎会自动操纵activeIndex,这是决定手风琴扩展和折叠的主要属性。如果你自己就像上面那样做,你需要维护所有的层次结构,并通过调整onClick处理程序中的状态来操纵自己。因此,如果您的用例不是自定义或复杂的,您可以尝试下面的内容。

这是一个有效的演示NESTED ACCORDION SEMANTIC UI

import { Accordion } from 'semantic-ui-react';

const AccordionContent = (content) => (
  <div className="indent">
    {content}
  </div>
)

const SubAccordion1Panels = [
  {
    title: 'Sub Accordion 11',
    content: { content: AccordionContent('11 Content'), key: '11-content'} ,
    key: 'sub-accordion-11'
  }, {
    title: 'Sub Accordion 12',
    content: { content: AccordionContent('12 Contents'), key: '12-content' },
    key: 'sub-accordion-12'
  }, {
    title: 'Sub Accordion 13',
    content: { content: AccordionContent('13 Contents'), key: '13-content' },
    key: 'sub-accordion-13'
  },
]

const SubAccordion1Content = (
  <div className="indent">
    <Accordion.Accordion
      style={{marginLeft: "20px"}}
      className="no-padding"
      panels={SubAccordion1Panels}
    />
  </div>
)

const SubAccordionPanels = [
  {
    title: 'Sub Accordion 1',
    content: { content: SubAccordion1Content, key: 'sa1-content' },
    key: 'sub-accordion-1'
  }, {
    title: 'Sub Accordion 2',
    content: { content: AccordionContent('SA2 Content'), key: 'sa2-content' },
    key: 'sub-accordion-2'
  }, {
    title: 'Sub Accordion 3',
    content: { content: AccordionContent('SA3 Content'), key: 'sa3-content' },
    key: 'sub-accordion-3'
  }
]

const SubAccordions = (
  <div className="indent">
    <Accordion.Accordion
      className="no-padding"
      panels={SubAccordionPanels}
    />
  </div>
)

const AccordionPanels = [
  { title: 'Accordion', content: { content: SubAccordions, key: 'sub-accordions' } },
]

const AccordionExampleNested = () => (
  <Accordion
    defaultActiveIndex={0}
    panels={AccordionPanels}
  />
)

class App extends React.Component {
  render() {
    return (
      <AccordionExampleNested />
    )
  }
}

同样对于缩进,您需要覆盖默认的css

.indent {
  margin-left: 1em;
}

.no-padding {
  padding: 0px !important;
  margin: 0px !important;
}