5 分钟精通 react-transition-group

11,168 阅读4分钟
  • react-transition-group 是 React 官方实现的,用于操作过渡效果的组件库,它不像 React-Motion 动画库,并没有给我们提供一些预置的动画效果
  • 该组件库提供了 4 个组件,方便开发者对元素动画的各个阶段进行监控,如 入场动画开始动画离开动画
  • 这 4 个组件的上手成本极低,且提供的功能足矣完成各种复杂的动画特效

Transition 组件

  • 默认情况下,Transition 组件不会改变它呈现的组件的行为,它只跟踪组件动画的 进入退出 状态,由开发者来赋予这些状态的实际意义和展现效果
  • 下面介绍 Transition 组件常用的 API
    • children:func
    • 一个函数,该函数接收当前动画的转换状态,返回页面实际需要渲染的子组件
      • 转换状态分为两类,进入状态 和 离开状态
      • 'entering' 当前为进入动画的展示中
      • 'entered' 当前为进入动画的最终状态
      • 'exiting' 当前为离开动画的展示中
      • 'exited' 当前为离开动画的最终状态
<Transition in={this.state.in} timeout={150}>
  {state => (
    <MyComponent className={`my-${state}`} />
  )}
</Transition>
  • in:boolean

    • 接收动画触发的状态,为 true 时触发 进入动画,为 false 时触发 离开动画
  • appear:boolean

    • 默认情况下,子组件在第一次挂载时,不管 in 的值为什么,组件都不会触发 进入动画
    • 如果想要子组件展示类似 入场动画 的效果,需要将 appear 与 in 都设置为 true
  • timeout:number

    • 动画的持续时间,单位为毫秒,可以一次设置所有状态的动画时间,也可以单独设置每个状态的动画时间
timeout={500}

// or

timeout={{
 appear: 500,
 enter: 300,
 exit: 500,
}}
  • addEndListener:func
    • 自定义 transition 结束的触发器,它允许开发者自定义更加细腻的动画结束逻辑
    • 其接收动画中的 dom 节点和一个动画结束的回调函数
addEndListener={(node, doneCallBack) => {
  // use the css transitionend event to 
  // mark the finish of a transition
  
  node.addEventListener('transitionend', doneCallBack);
}}
  • 各个动画阶段的钩子
    • 开始动画的三个钩子,均接收一个回调函数 Function(node: HtmlElement, isAppearing: bool) -> void,回调函数接收 2 个参数,第一个参数为当前元素的 dom 节点,第二个参数表示当前动画是否为元素初次挂载时发生
    • onEnter:在动画状态变为 entering 之前调用
    • onEntering:在动画状态变为 entering 之后调用
    • onEntered:在动画状态变为 entered 之后调用
    • 离开动画的三个钩子,均接收一个回调函数 Function(node: HtmlElement) -> void,回调函数仅接收当前元素的 dom 节点
    • onExit:在动画状态变为 exiting 之前调用
    • onExiting:在动画状态变为 exiting 之后调用
    • onExited:在动画状态变为 exited 之后调用

CSSTransition

  • 该组件继承自 Transition 组件,继承了 Transition 的所有 API
  • CSSTransition 组件在 Transition 提供的 开始动画 和 退出动画 的基础上,增加了 入场动画
  • 支持更加细分的动画的各个阶段,以开始动画为例,CSSTransition 会在其子组件的 class 上依次添加 *-enter, *-enter-active, *-enter-done
    • enter 表示开始动画的初始阶段
    • enter-active 表示开始动画的激活阶段
    • enter-done 表示开始动画的结束阶段,也是样式的持久化展示阶段
<CSSTransition in={flag} timeout={150}>
   <MyComponent />
</CSSTransition>
  • CSSTransition 增加的 API
    • classNames
      • 有两种使用方法,一种是提供一个统一的前缀字符串,它会自动给每个阶段的 class 名称加上这个前缀,另一种是提供一个对象,自己定义每个阶段的 class 名称
classNames="my"

// or

classNames={{
 appear: 'my-appear',
 appearActive: 'my-active-appear',
 appearDone: 'my-done-appear',
            
 enter: 'my-enter',
 enterActive: 'my-active-enter',
 enterDone: 'my-done-enter',
            
 exit: 'my-exit',
 exitActive: 'my-active-exit',
 exitDone: 'my-done-exit',
}}

SwitchTransition

  • SwitchTransition 组件是受 vue 过渡模式的启发而诞生的,也是继承自 Transition 组件
  • 当我们想要控制状态转换之间的渲染时,就可以使用 SwitchTransition
  • SwitchTransition 需要使用 Transition 或 CSSTransition 包裹需要渲染到页面的组件,来当做它的 children
<SwitchTransition>
  <CSSTransition
    key={state}
    addEndListener={
      (node, doneCallBack) => 
      	node.addEventListener("transitionend", doneCallBack)
    }
    classNames='my'
    >
    <MyComponent />
  </CSSTransition>
</SwitchTransition>
  • SwitchTransition 增加的 API
    • mode:'out-in' | 'in-out'
      • out-in: 表示 SwitchTransition 需要等待 old child 离开,然后插入 new child
      • in-out: 表示 SwitchTransition 需要等待插入 new child,然后移除 old child

TransitionGroup

  • 顾名思义,TransitionGroup 是来管理多个元素的动画效果,上面介绍的组件都是控制单个元素的动画效果
  • TransitionGroup 就像是一个状态机,可以管理子组件的挂载状态和卸载状态的动画
<TransitionGroup>
  {list.map(({ id }) => (
    <CSSTransition
      key={id}
      timeout={500}
      classNames="my"
    >
      <MyComponent key={id}/>
    </CSSTransition>
  ))}
</TransitionGroup>
  • TransitionGroup 新增的 API
    • component
    • 在默认情况下,TransitionGroup 会被渲染为一个 div,如果想要避免这样的行为,可以传入 null,component={null}
    • appear
      • 控制子组件是否展示 入场动画,默认为 true,它接收的值会覆盖掉子组件上对应的设置
    • enter
      • 控制子组件是否展示 开始动画,默认为 true,它接收的值会覆盖掉子组件上对应的设置
    • exit
      • 控制子组件是否展示 结束动画,默认为 true,它接收的值会覆盖掉子组件上对应的设置

示例与官网