过渡动画实现及CSS样式

66 阅读2分钟

1. 过渡动画

1.1 CSSTransation 动画

// App.jsx
import React, { createRef, PureComponent } from "react"
import { CSSTransition } from "react-transition-group"
import "./style.css"

export class App extends PureComponent {
  constructor() {
    super()

    this.state = {
      isShow: true
    }

    this.titleRef = createRef()
  }
  render() {
    const { isShow } = this.state
    return (
      <div>
        <button onClick={e => this.setState({ isShow: !isShow })}>toggle</button>
        <CSSTransition
          nodeRef={this.titleRef}
          in={isShow}
          unmountOnExit={true}
          classNames="lwz"
          timeout={2000}
          appear
          onEnter={e => console.log("开始进入动画")}
          onEntering={e => console.log("执行进入动画")}
          onEntered={e => console.log("执行进入结束")}
          onExit={e => console.log("开始离开动画")}
          onExiting={e => console.log("执行离开动画")}
          onExited={e => console.log("执行离开结束")}
        >
          <div className="section" ref={this.titleRef}>
            <h2>Hello React</h2>
            <p>I'm React Component</p>
          </div>
        </CSSTransition>
      </div>
    )
  }
}

export default App

// style.css
/* 首次进入动画 */
.lwz-appear {
  transform: translateX(-150px);
}
.lwz-appear-active {
  transform: translateX(0);
  transition: transform 2s ease;
}

/* 进入动画 */
.lwz-enter {
  opacity: 0;
}
.lwz-enter-active {
  opacity: 1;
  transition: opacity 2s ease;
}

/* 离开动画 */
.lwz-exit {
  opacity: 1;
}

.lwz-exit-active {
  opacity: 0;
  transition: opacity 2s ease;
}

1.2 SwitchTransation

// App.jsx
import React, { PureComponent } from "react"
import { SwitchTransition, CSSTransition } from "react-transition-group"
import "./style.css"

export class App extends PureComponent {
  constructor() {
    super()

    this.state = {
      isLogin: true
    }
  }
  render() {
    const { isLogin } = this.state
    return (
      <div>
        <SwitchTransition mode="out-in">
          <CSSTransition key={isLogin ? "exit" : "login"} timeout={1000} classNames="login">
            <button onClick={e => this.setState({ isLogin: !isLogin })}>{isLogin ? "退出" : "登录"}</button>
          </CSSTransition>
        </SwitchTransition>
      </div>
    )
  }
}

export default App

// style.css
.login-enter {
  transform: translateX(-100px);
  opacity: 0;
}
.login-enter-active {
  transform: translateX(0);
  opacity: 1;
  transition: all 1s ease;
}

.login-exit {
  transform: translateX(0);
  opacity: 1;
}
.login-exit-active {
  transform: translateX(100px);
  opacity: 0;
  transition: all 1s ease;
}

1.3 TransationGroup

// App.jsx
import React, { PureComponent } from "react"
import { TransitionGroup, CSSTransition } from "react-transition-group"
import "./style.css"

export class App extends PureComponent {
  constructor() {
    super()

    this.state = {
      books: [
        { id: 111, name: "JavaScript", price: 99 },
        { id: 222, name: "TypeScript", price: 88 },
        { id: 333, name: "JavaScriptReact", price: 77 }
      ]
    }
  }
  addNewBook() {
    const books = [...this.state.books]
    books.push({ id: new Date().getTime(), name: "React高级程序设计", price: 99 })
    this.setState({ books })
  }
  removeBook(index) {
    const books = [...this.state.books]
    books.splice(index, 1)
    this.setState({ books })
  }
  render() {
    const { books } = this.state
    return (
      <div>
        <h2>书籍列表:</h2>
        <TransitionGroup component="ul">
          {books.map((book, index) => {
            return (
              <CSSTransition key={book.id} classNames="book" timeout={1000}>
                <li>
                  <span>
                    {book.name}-{book.price}
                  </span>
                  {/* 一定要保证 key 值是唯一的,否则删除时会出现删除错乱 */}
                  <button onClick={e => this.removeBook(index)}>删除</button>
                </li>
              </CSSTransition>
            )
          })}
        </TransitionGroup>
        <button onClick={e => this.addNewBook()}>添加</button>
      </div>
    )
  }
}

export default App

// style.css
.book-enter {
  transform: translateX(100px);
  opacity: 0;
}

.book-enter-active {
  transform: translateX(0);
  opacity: 1;
  transition: all 1s ease;
}

.book-exit {
  transform: translateX(0);
  opacity: 1;
}

.book-exit-active {
  transform: translateX(-100px);
  opacity: 0;
  transition: all 1s ease;
}

2. CSS 样式

2.1 css_in_js

  • npm install styled-components
// App.jsx
import React, { PureComponent } from "react"
import { AppWrapper, SectionWrapper } from "./style"

export class App extends PureComponent {
  constructor() {
    super()

    this.state = {
      color: "yellow",
      size: 30
    }
  }
  render() {
    const { size } = this.state
    return (
      <AppWrapper>
        <SectionWrapper size={size}>
          <h2 className="title">我是标题</h2>
          <p className="content">我是内容, 哈哈哈</p>
          <button onClick={e => this.setState({ color: "skyblue" })}>toggle</button>
        </SectionWrapper>

        <div className="footer">
          <p>免责声明</p>
          <p>版权声明</p>
        </div>
      </AppWrapper>
    )
  }
}

export default App

// style.css
import styled from "styled-components"
export const AppWrapper = styled.div`
  .footer {
    border: 1px solid orange;
  }
`

// attrs 属性可以指定默认样式,此处需要写成函数形式
export const SectionWrapper = styled.div.attrs(props => ({
  tColor: props.color || "blue"
}))`
  border: 1px solid red;

  .title {
    font-size: ${props => props.size}px;
    color: ${props => props.tColor};

    &:hover {
      background-color: purple;
    }
  }

  .content {
    font-size: 20px;
    color: green;
  }
`

2.2 classNames库

  • npm install classNames
import React, { PureComponent } from "react"
import classNames from "classnames"

export class App extends PureComponent {
  constructor() {
    super()

    this.state = {
      isbbb: false,
      isccc: true
    }
  }
  render() {
    const { isbbb, isccc } = this.state
    return (
      <div>
        <h2 className={classNames("aaa", { bbb: isbbb, ccc: isccc })}>Hello React</h2>
        <h2 className={classNames(["aaa", { bbb: isbbb, ccc: isccc }])}>Hello World</h2>
      </div>
    )
  }
}

export default App