我使用React和样式组件创建了简单的accordion。我有一个问题,使效果,使较低的部分可以慢慢滑出,而不是立即弹出。我使用了一个过渡,但我不知道为什么它在我的情况下不起作用。下面是我的部分代码:https://codesandbox.io/s/sweet-blackwell-v78wt?file=/src/App.js
发布于 2020-10-06 03:52:38
为了获得最佳效果,您需要将max-height从0px转换为内容高度,反之亦然。您将需要使用useRef和useEffect挂钩来选择元素并手动设置元素上的样式。
您还需要一个知道内容高度的内部包装器。这将是在折叠容器上设置max-height的参考。
使用onTransitionEnd事件侦听器,可以在展开折叠面板时移除max-height属性。这使元素能够根据内容相应地调整大小。
内容的高度由getBoundingClientRect()函数决定。它返回一个具有元素高度、宽度(以及更多)的对象。这样,您就可以确定内容容器的高度。
下面的示例是一个基于您的代码的可行示例。
import React, { useState, useRef, useEffect } from "react";
import "./styles.css";
import styled from "styled-components";
const Accordion = () => {
const [isExpanded, setIsExpanded] = useState(false);
const [isAnimating, setIsAnimating] = useState(false);
const collapseRef = useRef(null);
const contentRef = useRef(null);
const handleClick = () => {
/**
* isAnimating prevents the accordion from changing
* state when it is in the middle of a transition.
*/
if (!isAnimating) {
setIsAnimating(true);
setIsExpanded((isExpanded) => !isExpanded);
}
};
const handleTransition = () => {
if (isExpanded) {
/**
* Removing the max-height when expanded makes sure
* that the element still resizes responsively correct.
*/
collapseRef.current.style.maxHeight = "";
}
setIsAnimating(false);
};
useEffect(() => {
const { height } = contentRef.current.getBoundingClientRect();
collapseRef.current.style.maxHeight = `${height}px`;
if (!isExpanded) {
/**
* This makes sure that the element first is expanded
* and in the next frame paint is transitioned to 0px.
* Otherwise the 0px height would overwrite to dynamic height
* and there'd be no transition.
*/
requestAnimationFrame(() => {
collapseRef.current.style.maxHeight = "0px";
});
}
}, [isExpanded]);
return (
<ContentWrapper onClick={handleClick}>
<TitleCard>
<h2>Example text</h2>
</TitleCard>
<DescriptionCard
ref={collapseRef}
isVisible={isExpanded}
style={{ maxHeight: "0px" }}
onTransitionEnd={handleTransition}
>
<DescriptionContent ref={contentRef}>
<p>Example text 2</p>
<p>Now it expands based on the height of the</p>
<h3>content.</h3>
<p>Now it expands based on the height of the</p>
<h3>content.</h3>
</DescriptionContent>
</DescriptionCard>
</ContentWrapper>
);
};
export default function App() {
return (
<div className="App">
<Accordion />
</div>
);
}
const DescriptionContent = styled.div`
display: flex;
flex-direction: column;
`;
const DescriptionCard = styled.div`
background: grey;
overflow: hidden;
align-items: center;
justify-content: flex-start;
transition: max-height 0.35s;
`;
const TitleCard = styled.div`
cursor: pointer;
height: 4.8rem;
background: #ffffff;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
padding: 0 1.5em;
`;
const ContentWrapper = styled.div`
border-radius: 16px;
border: 2px solid black;
overflow: hidden;
`;https://stackoverflow.com/questions/64214329
复制相似问题