>

React에서 나만의 반응 형 아코디언을 구현했으며폴드의 오프닝을 애니메이션으로 만들 수 없습니다.

제목 앞에서 아이콘을 위아래로 움직일 수 있기 때문에 특히 이상합니다. 아이콘이 의사 요소 인 것 외에는 둘 사이의 차이점을 볼 수없는 것 같습니다.

JS :

class Accordion extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      active: -1
    };
  }
  /***
   * Selects the given fold, and deselects if it has been clicked again by setting "active to -1" 
   * */
  selectFold = foldNum => {
    const current = this.state.active === foldNum ? -1 : foldNum;
    this.setState(() => ({ active: current }));
  };
  render() {
    return (
      <div className="accordion">
        {this.props.contents.map((content, i) => {
          return (
            <Fold
              key={`${i}-${content.title}`}
              content={content}
              handle={() => this.selectFold(i)}
              active={i === this.state.active}
            />
          );
        })}
      </div>
    );
  }
}
class Fold extends React.Component {
  render() {
    return (
      <div className="fold">
        <button
          className={`fold_trigger ${this.props.active ? "open" : ""}`}
          onClick={this.props.handle}
        >
          {this.props.content.title}
        </button>
          <div
            key="content"
            className={`fold_content ${this.props.active ? "open" : ""}`}
          >
            {this.props.active ? this.props.content.inner : null}
          </div>
      </div>
    );
  }
}

CSS :

$line-color: rgba(34, 36, 38, 0.35);
.accordion {
  width: 100%;
  padding: 1rem 2rem;
  display: flex;
  flex-direction: column;
  border-radius: 10%;
  overflow-y: auto;
}
.fold {
  .fold_trigger {
    &:before {
      font-family: FontAwesome;
      content: "\f107";
      display: block;
      float: left;
      padding-right: 1rem;
      transition: transform 400ms;
      transform-origin: 20%;
      color: $line-color;
    }
    text-align: start;
    width: 100%;
    padding: 1rem;
    border: none;
    outline: none;
    background: none;
    cursor: pointer;
    border-bottom: 1px solid $line-color;
    &.open {
      &:before {
        transform: rotateZ(-180deg);
      }
    }
  }
  .fold_content {
    display: none;
    max-height: 0;
    opacity: 0;
    transition: max-height 400ms linear;
    &.open {
      display: block;
      max-height: 400px;
      opacity: 1;
    }
  }
  border-bottom: 1px solid $line-color;
}

코드 펜은 다음과 같습니다. https://codepen.io/renzyq19/pen/bovZKj


  • 답변 # 1

    원활한 전환을 원한다면 콘텐츠를 조건부로 렌더링하지 않습니다. 슬라이드 업 애니메이션을 특히 까다로울 수 있습니다.

    <시간>

    이것을 변경하겠습니다 :

    {this.props.active ? this.props.content.inner : null}
    
    

    이것에 대해 :

    {this.props.content.inner}
    
    

    scss 를 사용하십시오 :

    .fold_content {
      max-height: 0;
      overflow: hidden;
      transition: max-height 400ms ease;
      &.open {
        max-height: 400px;
      }
    }
    
    
    <시간>

    아래 스 니펫을 사용해 보거나 갈래의CodePen 데모를 참조하십시오.

    class Accordion extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          active: -1
        };
      }
      /***
       * Selects the given fold, and deselects if it has been clicked again by setting "active to -1" 
       * */
      selectFold = foldNum => {
        const current = this.state.active === foldNum ? -1 : foldNum;
        this.setState(() => ({ active: current }));
      };
      render() {
        return (
          <div className="accordion">
            {this.props.contents.map((content, i) => {
              return (
                <Fold
                  key={`${i}-${content.title}`}
                  content={content}
                  handle={() => this.selectFold(i)}
                  active={i === this.state.active}
                />
              );
            })}
          </div>
        );
      }
    }
    class Fold extends React.Component {
      render() {
        return (
          <div className="fold">
            <button
              className={`fold_trigger ${this.props.active ? "open" : ""}`}
              onClick={this.props.handle}
            >
              {this.props.content.title}
            </button>
              <div
                key="content"
                className={`fold_content ${this.props.active ? "open" : ""}`}
              >
                {this.props.content.inner}
              </div>
          </div>
        );
      }
    }
    const pictures = [
      "http://unsplash.it/200",
      "http://unsplash.it/200",
      "http://unsplash.it/200",
    ];
    var test = (title, text, imageURLs) => {
      const images=
        <div className='test-images' >
          {imageURLs.map((url,i) => <img key={i} src={url} />)}
        </div>;
      const inner =
        <div className='test-content' >
          <p>{text} </p>
          {images} 
        </div>;
      
      return {title, inner};
    };
    const testData = [
      test('Title', 'Content',pictures ),
      test('Title', 'Content',pictures ),
      test('Title', 'Content',pictures ),
      test('Title', 'Content',pictures ),
      test('Title', 'Content',pictures ),
    ];
    ReactDOM.render(<Accordion contents={testData} />, document.getElementById('root'));
    
    
    .accordion {
      width: 100%;
      padding: 1rem 2rem;
      display: flex;
      flex-direction: column;
      border-radius: 10%;
      overflow-y: auto;
    }
    .fold {
      border-bottom: 1px solid rgba(34, 36, 38, 0.35);
    }
    .fold .fold_trigger {
      text-align: start;
      width: 100%;
      padding: 1rem;
      border: none;
      outline: none;
      background: none;
      cursor: pointer;
      border-bottom: 1px solid rgba(34, 36, 38, 0.35);
    }
    .fold .fold_trigger:before {
      font-family: FontAwesome;
      content: "\f107";
      display: block;
      float: left;
      padding-right: 1rem;
      transition: transform 400ms;
      transform-origin: 20%;
      color: rgba(34, 36, 38, 0.35);
    }
    .fold .fold_trigger.open:before {
      transform: rotateZ(-180deg);
    }
    .fold .fold_content {
      max-height: 0;
      overflow: hidden;
      transition: max-height 400ms ease;
    }
    .fold .fold_content.open {
      max-height: 400px;
    }
    
    
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet" />
    <div id='root'></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    
    

    참고 :

    ease 를 사용했습니다   linear 대신  더 좋은 효과라고 생각하기 때문에 전환에. 그러나 그것은 단지 개인적인 취향입니다. 와이즈 비즈  잘 작동합니다.

    또한 조건부로 콘텐츠를 계속 렌더링 할 수 있습니다. 슬라이드 다운 애니메이션은 가능하지만 슬라이드 업을 쉽게 수행 할 수는 없습니다. 탐색 할 수있는 일부 전환 라이브러리가 있습니다.

    그러나, 나는 당신이 linear 로하고있는 것처럼 조건부 클래스에 대해서만 상태를 사용하는 것이 가장 쉽다고 생각합니다.  수업). 조건부로 컨텐츠를 DOM에 렌더링하면 CSS 애니메이션을 수행하려는 경우 삶이 어려워집니다.

    open

  • 이전 xslt - 요소에 여러 특성이있는 XML을 변환하고 하나의 특성을 사용하여 새 요소를 작성하십시오
  • 다음 python - 객체 데이터에 작용하지 않는 메소드를 정적으로 만들어야합니까?