过渡
使用 CSS 类控制条件渲染元素的过渡样式,包括嵌套的子级过渡。
要开始,请通过 npm 安装无头 UI
npm install @headlessui/react
要使条件渲染元素过渡,请将其包裹在 Transition
组件中,并使用 show
属性指示它是打开还是关闭。
然后,使用原生 CSS 过渡样式应用动画,通过定位 Transition
组件公开的 data-closed
属性来指定元素的关闭样式。
import { Transition } from '@headlessui/react'
import { useState } from 'react'
function Example() {
const [open, setOpen] = useState(false)
return (
<>
<button onClick={() => setOpen((open) => !open)}>Toggle</button>
<Transition show={open}>
<div className="transition duration-300 ease-in data-[closed]:opacity-0">I will fade in and out</div>
</Transition>
</>
)
}
使用 data-closed
属性定义的样式将用作过渡时的起点,以及过渡时的终点。
对于更复杂的过渡,您还可以使用 data-enter
、data-leave
和 data-transition
属性在过渡的不同阶段应用样式。
使用 data-enter
和 data-leave
属性在进入和离开时应用不同的过渡样式
import { Transition } from '@headlessui/react'
import clsx from 'clsx'
import { useState } from 'react'
function Example() {
const [open, setOpen] = useState(false)
return (
<div className="relative">
<button onClick={() => setOpen((open) => !open)}>Toggle</button>
<Transition show={open}>
<div
className={clsx([
// Base styles
'absolute w-48 border transition ease-in-out',
// Shared closed styles
'data-[closed]:opacity-0',
// Entering styles
'data-[enter]:duration-100 data-[enter]:data-[closed]:-translate-x-full',
// Leaving styles
'data-[leave]:duration-300 data-[leave]:data-[closed]:translate-x-full',
])}
>
I will enter from the left and leave to the right
</div>
</Transition>
</div>
)
}
此示例结合了 data-enter
和 data-closed
属性来指定进入过渡的起点,并将 data-leave
和 data-closed
属性结合起来指定离开过渡的终点。
它还使用 data-enter
和 data-leave
属性指定不同的进入和离开持续时间。
有时您需要使用不同的动画过渡多个元素,但所有这些动画都基于相同的状态。例如,假设用户单击一个按钮打开一个滑过屏幕的侧边栏,并且您还需要同时淡入背景。
您可以通过使用父级 Transition
组件包裹相关元素,并使用 TransitionChild
组件包裹每个需要其自身过渡样式的子元素来实现这一点,TransitionChild
组件将自动与父级 Transition
通信并继承父级的 open
状态。
import { Transition, TransitionChild } from '@headlessui/react'
import { useState } from 'react'
function Example() {
const [open, setOpen] = useState(false)
return (
<>
<button onClick={() => setOpen(true)}>Open</button>
{/* The `show` prop controls all nested `TransitionChild` components. */}
<Transition show={open}> {/* Backdrop */}
<TransitionChild> <div
className="fixed inset-0 bg-black/30 transition duration-300 data-[closed]:opacity-0"
onClick={() => setOpen(false)}
/>
</TransitionChild>
{/* Slide-in sidebar */}
<TransitionChild> <div className="fixed inset-y-0 left-0 w-64 bg-white transition duration-300 data-[closed]:-translate-x-full">
{/* ... */}
</div> </TransitionChild> </Transition>
</>
)
}
TransitionChild
组件与 Transition
组件具有完全相同的 API,但没有 show
属性,因为 show
值由父级控制。
父级 Transition
组件将始终自动等待所有子级完成过渡,然后再卸载,因此您无需自己管理任何时间安排。
如果您希望元素在首次渲染时过渡,请将 appear
属性设置为 true
。
如果希望在页面初始加载时或父级条件渲染时某个元素过渡,这将非常有用。
import { Transition } from '@headlessui/react'
import { useState } from 'react'
function Example() {
const [open, setOpen] = useState(true)
return (
<>
<button onClick={() => setOpen((open) => !open)}>Toggle</button>
<Transition show={open} appear={true}> <div className="transition duration-300 ease-in data-[closed]:opacity-0">I will fade in on initial render</div>
</Transition>
</>
)
}
属性 | 默认值 | 描述 |
as | Fragment | 字符串 | 组件 元素或组件过渡应渲染为。 |
show | — | 布尔值 是否应该显示或隐藏子元素。 |
appear | false | 布尔值 是否应该在初始挂载时运行过渡。 |
unmount | true | 布尔值 根据 show 状态是否应该卸载或隐藏元素。 |
beforeEnter | — | () => void 在开始进入过渡之前调用的回调。 |
afterEnter | — | () => void 在完成进入过渡之后调用的回调。 |
beforeLeave | — | () => void 在开始离开过渡之前调用的回调。 |
afterLeave | — | () => void 在完成离开过渡之后调用的回调。 |
属性 | 默认值 | 描述 |
as | Fragment | 字符串 | 组件 元素或组件过渡子元素应渲染为。 |
appear | false | 布尔值 是否应该在初始挂载时运行过渡。 |
unmount | true | 布尔值 根据 show 状态是否应该卸载或隐藏元素。 |
beforeEnter | — | () => void 在开始进入过渡之前调用的回调。 |
afterEnter | — | () => void 在完成进入过渡之后调用的回调。 |
beforeLeave | — | () => void 在开始离开过渡之前调用的回调。 |
afterLeave | — | () => void 在完成离开过渡之后调用的回调。 |
属性 | 描述 |
data-closed | 在过渡之前和过渡时存在。 |
data-enter | 在过渡时存在。 |
data-leave | 在过渡时存在。 |
data-transition | 在过渡时存在。 |