【问题标题】:Expand/Collapse all data展开/折叠所有数据
【发布时间】:2021-01-15 03:40:08
【问题描述】:

我正在制作手风琴,当我们单击每个单独的项目时,它会打开或关闭。

现在我已经实现了全部展开或全部折叠选项以使所有手风琴展开/折叠。

Accordion.js

  const accordionArray = [
    { heading: "Heading 1", text: "Text for Heading 1" },
    { heading: "Heading 2", text: "Text for Heading 2" },
    { heading: "Heading 3", text: "Text for Heading 3" }
  ];
  .

  .

  .
{accordionArray.map((item, index) => (
        <div key={index}>
          <Accordion>
            <Heading>
              <div className="heading-box">
                <h1 className="heading">{item.heading}</h1>
              </div>
            </Heading>
            <Text expandAll={expandAll}>
              <p className="text">{item.text}</p>
            </Text>
          </Accordion>
        </div>
      ))}

text.js 是一个文件,我在其中执行打开手风琴的任何特定内容的操作,代码如下,

import React from "react";

class Text extends React.Component {
  render() {
    return (
      <div style={{ ...this.props.style }}>
        {this.props.expandAll ? (
          <div className={`content open`}>
            {this.props.render && this.props.render(this.props.text)}
          </div>
        ) : (
          <div className={`content ${this.props.text ? "open" : ""}`}>
            {this.props.text ? this.props.children : ""}
            {this.props.text
              ? this.props.render && this.props.render(this.props.text)
              : ""}
          </div>
        )}
      </div>
    );
  }
}

export default Text;

这里通过this.props.expandAll 我得到了expandAll 是真还是假的值。如果是真的,那么所有的手风琴都会得到className={`content open`} 的类,所以所有的都会被打开。

问题:

open 类已应用,但内部文本内容未呈现。

所以这条线行不通,

{this.props.render && this.props.render(this.props.text)}

要求:

如果单击全部展开/全部折叠按钮,则应分别打开/关闭所有手风琴。

这应该不考虑之前打开/关闭的手风琴。所以如果全部展开,那么它应该打开所有的手风琴,否则需要关闭所有的手风琴,即使它之前打开/关闭了。

链接:

这是文件https://codesandbox.io/s/react-accordion-forked-sm5fw?file=/src/GetAccordion.js 的链接,其中实际上传递了道具。

编辑:

如果我使用{this.props.children},那么每个手风琴都会打开。没有问题。

但是,如果我在单击特定项目时手动打开任何手风琴,那么如果我单击全部展开然后它的展开(预期)但是如果我单击返回折叠所有选项然后 不是全部手风琴关闭。 . 我们之前打开的那些仍然处于打开状态.. 但这里的预期行为是一切都应该关闭。

【问题讨论】:

    标签: javascript css reactjs accordion collapse


    【解决方案1】:

    在你的文件 text.js 中

    在第 9 行。请将之前的代码替换为: {this.props.children}

    在沙盒中尝试并为我工作。

    /// 无法添加评论,因此编辑答案本身。 Accordian.js 包含您的钩子 expandAll 并且标题布尔值已经发生 GetAccordian.js。 我建议将 expand all 移至 GetAccordian.js,以便您可以控制这两个值。

    【讨论】:

    • 感谢您的回答.. 但是在这里,如果我单击标题 2 并单击全部展开,那么所有内容都会打开,所以很好.. 但是如果我全部折叠,标题 2 仍然打开,而它应该全部折叠手风琴..
    • 另外,如果我手动打开所有手风琴并单击展开,则没有任何反应(预期)。但是,如果我再次单击全部折叠,则没有手风琴关闭所有内容仍然打开..那么您能帮我修复手动打开和折叠所有内容应该折叠所有内容吗?
    【解决方案2】:

    在这种情况下 this.props.render 不是函数并且 this.props.text 未定义,请尝试替换此行

      <div className={`content open`}>
        {this.props.render && this.props.render(this.props.text)}
      </div>
    

    通过这个:

      <div className={`content open`}>
       {this.props.children}
      </div>
    

    编辑:// 其他解决方案是将 expandAll 属性传递给 Accordion 组件

      <Accordion expandAll={expandAll}>
        <Heading>
          <div className="heading-box">
            <h1 className="heading">{item.heading}</h1>
          </div>
        </Heading>
        <Text>
          <p className="text">{item.text}</p>
        </Text>
      </Accordion>
    

    然后在 getAccordion.js 中

    onShow = (i) => {
          this.setState({
            active: this.props.expandAll ? -1: i,
            reserve: this.props.expandAll ? -1: i
          });
    
          if (this.state.reserve === i) {
            this.setState({
              active: -1,
              reserve: -1
            });
          }
        };
    
        render() {
          const children = React.Children.map(this.props.children, (child, i) => {
            return React.cloneElement(child, {
              heading: this.props.expandAll || this.state.active === i,
              text: this.props.expandAll || this.state.active + stage === i,
              onShow: () => this.onShow(i)
            });
          });
          return <div className="accordion">{children}</div>;
        }
      };
    

    【讨论】:

    • 感谢您的回答.. 但是在这里,如果我单击标题 2 并单击全部展开,那么所有内容都会打开,所以很好.. 但是如果我全部折叠,标题 2 仍然打开,而它应该全部折叠手风琴..
    • 另外,如果我手动打开所有手风琴并单击展开,则没有任何反应(预期)。但是,如果我再次单击全部折叠,则没有手风琴关闭所有内容仍然打开..那么您能帮我修复手动打开和折叠所有内容应该折叠所有内容吗?
    • 再次感谢,我已经通过 getAccordion.js 中的 componentDidUpdate mentod 实现了它,就像这里 codesandbox.io/s/react-accordion-forked-x7dsc 通过将道具传递给 Accordion。
    • 但是我已经在这里codesandbox.io/s/react-accordion-forked-74ui7 实现了您的解决方案,还有一个问题是,如果我们展开所有手风琴,则无法在单击任何特定手风琴时手动关闭它。
    • 是的,您的解决方案看起来更好;)
    【解决方案3】:

    基于@lissettdm 的回答,我不清楚为什么getAccordionaccordion 是两个独立的实体。您可能有一个非常正当的分离理由,但是这两个组件的状态是相互依赖的这一事实暗示它们可能更好地作为一个组件实现。

    Accordion 现在像以前一样直接控制其子项的状态,但不使用 getAccordion。现在,切换 expandAll 也会重置各个项目的状态。

    const NormalAccordion = () => {
      const accordionArray = [ //... your data ];
    
      const [state, setState] = useState({
        expandAll: false,
        ...accordionArray.map(item => false),
      });
    
      const handleExpandAll = () => {
        setState((prevState) => ({
          expandAll: !prevState.expandAll,
          ...accordionArray.map(item => !prevState.expandAll),
        }));
      };
    
      const handleTextExpand = (id) => {
        setState((prevState) => ({
          ...prevState,
          [id]: !prevState[id]
        }));
      };
    
      return (
        <>
          <div className="w-full text-right">
            <button onClick={handleExpandAll}>
              {state.expandAll ? `Collapse All` : `Expand All`}
            </button>
          </div>
          <br />
          {accordionArray.map((item, index) => (
            <div key={index}>
              <div className="accordion">
                <Heading handleTextExpand={handleTextExpand} id={index}>
                  <div className="heading-box">
                    <h1 className="heading">{item.heading}</h1>
                  </div>
                </Heading>
                <Text shouldExpand={state[index]}>
                  <p className="text">{item.text}</p>
                </Text>
              </div>
            </div>
          ))}
        </>
      );
    };
    

    标题将索引传回,以便父组件知道要关闭哪个项目。

    class Heading extends React.Component {
      handleExpand = () => {
        this.props.handleTextExpand(this.props.id);
      };
    
    
      render() {
        return (
          <div
            style={ //... your styles}
            onClick={this.handleExpand}
          >
            {this.props.children}
          </div>
        );
      }
    }
    

    Text 只关心一个 prop 来确定它是否应该显示展开内容。

    class Text extends React.Component {
      render() {
        return (
          <div style={{ ...this.props.style }}>
            <div
              className={`content ${this.props.shouldExpand ? "open" : ""}`}
            >
              {this.props.shouldExpand ? this.props.children : ""}
            </div>
          </div>
        );
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-29
      • 2021-11-10
      • 2016-05-31
      • 2015-07-03
      • 1970-01-01
      • 2021-07-23
      • 1970-01-01
      相关资源
      最近更新 更多