vue/组件化/Transition组件

94 阅读1分钟

解决的问题

为组件的出现、消失添加过渡的东西效果

工作原理

  • 当 DOM 元素被挂载时,将动效附加到该 DOM 元素上;
  • 当 DOM 元素被卸载时,不要立即卸载 DOM 元素,而是等到附加到该 DOM 元素上的动效执行完成后再卸载它。

使用原生dom的实现

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://unpkg.com/@vue/reactivity@3.0.5/dist/reactivity.global.js"></script>
    <title>Document</title>
    <style>
        #div {
            position: relative;
            width: 100px;
            height: 100px;
            border: 1px solid black
        }

        .enter-from {
            transform: translateX(200px);
        }

        .enter-active {
            transition: all ease-in 3s;
        }

        .enter-to {
            transform: translateX(0);
        }
    </style>
</head>

<body>
    <div id="div"></div>
</body>
<script>
    let div = document.getElementById("div")
    enterAnimation(div)
    div.addEventListener('click',()=>{
        outerAnimation(div)
    })
    function enterAnimation(div) {
        div.classList.add('enter-from')
        div.classList.add('enter-active')

        // 下一帧,再执行动画的过渡效果,执行完毕后,卸载动画
        requestAnimationFrame(() => {
            div.classList.remove('enter-from')
            div.classList.add('enter-to')

            div.addEventListener('transitionend', () => {
                div.classList.remove('enter-to')
                div.classList.remove('enter-active')
            })
        })
    }
    function outerAnimation(div) {
        div.classList.add('enter-to')
        div.classList.add('enter-active')

        // 下一帧,再执行动画的过渡效果,执行完毕后,卸载元素
        requestAnimationFrame(() => {
            div.classList.remove('enter-to')
            div.classList.add('enter-from')

            div.addEventListener('transitionend', () => {
                document.body.removeChild(div)
            })
        })
    }
</script>

</html>

api说明

interface TransitionProps {
  /**
   * 用于自动生成过渡 CSS class 名。
   * 例如 `name: 'fade'` 将自动扩展为 `.fade-enter`   * `.fade-enter-active` 等。
   */
  name?: string
  /**
   * 是否应用 CSS 过渡 class。
   * 默认:true
   */
  css?: boolean
  /**
   * 指定要等待的过渡事件类型
   * 来确定过渡结束的时间。
   * 默认情况下会自动检测
   * 持续时间较长的类型。
   */
  type?: 'transition' | 'animation'
  /**
   * 显式指定过渡的持续时间。
   * 默认情况下是等待过渡效果的根元素的第一个 `transitionend`
   *`animationend`事件。
   */
  duration?: number | { enter: number; leave: number }
  /**
   * 控制离开/进入过渡的时序。
   * 默认情况下是同时的。
   */
  mode?: 'in-out' | 'out-in' | 'default'
  /**
   * 是否对初始渲染使用过渡。
   * 默认:false
   */
  appear?: boolean

  /**
   * 用于自定义过渡 class 的 prop。
   * 在模板中使用短横线命名,例如:enter-from-class="xxx"
   */
  enterFromClass?: string
  enterActiveClass?: string
  enterToClass?: string
  appearFromClass?: string
  appearActiveClass?: string
  appearToClass?: string
  leaveFromClass?: string
  leaveActiveClass?: string
  leaveToClass?: string
}

测试代码

<Transition>
  <div v-if="ok">toggled content</div>
</Transition>