我们先搭建一个空白工程化项目
这个示例工程。是一个计数器。
import * as React from "react";import { Component } from "react";interface AppProps { }interface AppState { count: number; } export default class App extends Component{ constructor(props: AppProps) { super(props); this.increase = this.increase.bind(this); this.decrease = this.decrease.bind(this); this.state = { count: 0 }; } private decrease() { this.setState({ count: this.state.count - 1 }); } private increase() { this.setState({ count: this.state.count + 1 }); } render() { var { count } = this.state; return <> Hello World!
{count}>; } }
接下来我们创建一个组件
这个组件有展开和收起 2 种状态。修改传入的属性,可以切换 className
import * as React from "react";import { Component } from "react";import "./CollapseBody.scss";export interface CollapseBodyProps { open?: boolean; }export class CollapseBody extends Component{ render() { let { open, children } = this.props; let classList = ["collapse-body"]; if(open) { classList.push('collapse-body_open'); } else { classList.push('collapse-body_close'); } return {children}; } }
接下来我们引入组件
直接在刚刚的计数器上改一下,这样在计数的时候就会切换展开收起状态。
import * as React from "react";import { Component } from "react";import { CollapseBody } from "./Components/Collapse/CollapseBody";interface AppProps { }interface AppState { count: number; } export default class App extends Component{ constructor(props: AppProps) { super(props); this.increase = this.increase.bind(this); this.decrease = this.decrease.bind(this); this.state = { count: 0 }; } private decrease() { this.setState({ count: this.state.count - 1 }); } private increase() { this.setState({ count: this.state.count + 1 }); } render() { var { count } = this.state; return <> Hello World!
{count}asdasdas >; } }
接下来我们看看效果
我们可以看到按钮时 class 在切换
接下来编写样式
展开时高度是 calc-size (auto , size);收起时,高度是 0;在加以 transition 和 overflow 就完成了。
我们试一下,在高版本正常过渡,低版本由于不支持 calc-size (auto, size),于是高度为默认值 auto,没有过渡动画,但是不影响使用。
.collapse-body { transition: height .3s; overflow-y: hidden; height: calc-size(auto, size); }.collapse-body_close { height: 0; }
overflow 和 display 优化
上面代码虽然能用但是还不够完美,有 2 个问题。
- 首先容器含有 overflow:hidden,会导致内部内容被截断,如果内部内容还有 box-shadow,很容易被截掉。最好是只在过渡时含有 overflow:hidden。
- 还有收起后应当含有 disaplay:none,否则收起后仍然占据体积,在一些情况下会出现不必要的滚动条。
我们可以使用 animation 进行改造。
.collapse-body_close { display: none; } @supports(height: calc-size(auto, size)) { .collapse-body_open { animation: collapseBodyIn .3s; } .collapse-body_close { animation: collapseBodyOut .3s; } } @keyframes collapseBodyIn { from { overflow-y: hidden; height: 0; } to { overflow-y: hidden; height: calc-size(auto, size); } } @keyframes collapseBodyOut { from { overflow-y: hidden; display: block; height: calc-size(auto, size); } to { overflow-y: hidden; display: block; height: 0; } }