这是Dify Web的一个Loading组件,用于控制整个页面的加载动画效果,接下来我们学习这个动画的用法。
import React from 'react'
import './style.css'
type ILoadingProps = {
type?: 'area' | 'app'
}
const Loading = (
{ type = 'area' }: ILoadingProps = { type: 'area' },
) => {
return (
<div className={`flex w-full justify-center items-center ${type === 'app' ? 'h-full' : ''}`}>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className='spin-animation'>
<g clipPath="url(#clip0_324_2488)">
<path d="M15 0H10C9.44772 0 9 0.447715 9 1V6C9 6.55228 9.44772 7 10 7H15C15.5523 7 16 6.55228 16 6V1C16 0.447715 15.5523 0 15 0Z" fill="#1C64F2" />
<path opacity="0.5" d="M15 9H10C9.44772 9 9 9.44772 9 10V15C9 15.5523 9.44772 16 10 16H15C15.5523 16 16 15.5523 16 15V10C16 9.44772 15.5523 9 15 9Z" fill="#1C64F2" />
<path opacity="0.1" d="M6 9H1C0.447715 9 0 9.44772 0 10V15C0 15.5523 0.447715 16 1 16H6C6.55228 16 7 15.5523 7 15V10C7 9.44772 6.55228 9 6 9Z" fill="#1C64F2" />
<path opacity="0.2" d="M6 0H1C0.447715 0 0 0.447715 0 1V6C0 6.55228 0.447715 7 1 7H6C6.55228 7 7 6.55228 7 6V1C7 0.447715 6.55228 0 6 0Z" fill="#1C64F2" />
</g>
<defs>
<clipPath id="clip0_324_2488">
<rect width="16" height="16" fill="white" />
</clipPath>
</defs>
</svg>
</div>
)
}
export default Loading
Style:
.spin-animation path {
animation: custom 2s linear infinite;
}
@keyframes custom {
0% {
opacity: 0;
}
25% {
opacity: 0.1;
}
50% {
opacity: 0.2;
}
75% {
opacity: 0.5;
}
100% {
opacity: 1;
}
}
.spin-animation path:nth-child(1) {
animation-delay: 0s;
}
.spin-animation path:nth-child(2) {
animation-delay: 0.5s;
}
.spin-animation path:nth-child(3) {
animation-delay: 1s;
}
.spin-animation path:nth-child(4) {
animation-delay: 2s;
}
这是一个 React 组件 Loading
,用于显示一个加载动画。以下是代码的详细解析:
功能
- 该组件渲染一个 SVG 旋转动画,用于表示“加载中”状态。
- 组件支持
type
传参,决定其在不同场景下的样式:area
(默认值):适用于局部区域的加载动画。app
:适用于整个应用的加载动画(h-full
表示高度填充整个父容器)。
代码解析
1. 组件定义
import React from 'react'
import './style.css'
- 这是一个 React 组件,使用了 TypeScript,并且引入了
style.css
进行样式控制。
type ILoadingProps = {
type?: 'area' | 'app'
}
- 定义了
ILoadingProps
类型,type
可选,值为'area'
或'app'
,默认为'area'
。
2. 组件实现
const Loading = (
{ type = 'area' }: ILoadingProps = { type: 'area' },
) => {
- 这里使用了解构赋值,并给
type
设定默认值'area'
。 - 该组件是一个函数式组件。
3. 样式 & 结构
return (
<div className={`flex w-full justify-center items-center ${type === 'app' ? 'h-full' : ''}`}>
div
采用了flex
布局,使加载动画居中对齐。w-full
:宽度填充整个容器。justify-center items-center
:水平 & 垂直居中。type === 'app' ? 'h-full' : ''
:app
模式下,高度填充整个容器(适用于全屏加载)。area
模式下,高度不受影响。
4. SVG 加载动画
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className='spin-animation'>
- 加载动画是一个 16x16 像素的 SVG,使用了
spin-animation
CSS 动画(是一个旋转动画)。
<g clipPath="url(#clip0_324_2488)">
<path d="M15 0H10C9.44772 0 9 0.447715 9 1V6C9 6.55228 9.44772 7 10 7H15C15.5523 7 16 6.55228 16 6V1C16 0.447715 15.5523 0 15 0Z" fill="#1C64F2" />
- 这个
<path>
定义了 SVG 的四个不同方块,每个方块有不同的透明度,实现类似“旋转进度条”的视觉效果。
<defs>
<clipPath id="clip0_324_2488">
<rect width="16" height="16" fill="white" />
</clipPath>
</defs>
clipPath
可能用于裁剪图形。
5. 导出组件
export default Loading
- 该组件被
export default
导出,以便其他组件导入并使用。
总结
Loading
组件 是一个可复用的加载动画组件,适用于局部或全局加载状态。- 使用方法
<Loading /> // 局部加载(默认) <Loading type="app" /> // 全屏加载
- 动画效果 依赖
style.css
中的.spin-animation
,应该是一个旋转动画。
使用
在 React 组件中,通常通过 状态(state) 控制 Loading
组件的显示和隐藏。例如,你可以在父组件中使用 useState
来管理加载状态,当加载完成后隐藏 Loading
组件。
方法 1:使用 useState
控制 Loading
的显示
在父组件中:
import React, { useState, useEffect } from 'react'
import Loading from './Loading'
const App = () => {
const [loading, setLoading] = useState(true)
useEffect(() => {
// 模拟加载过程(例如 API 请求)
setTimeout(() => {
setLoading(false) // 加载完成后隐藏 Loading
}, 3000)
}, [])
return (
<div>
{loading ? <Loading type="app" /> : <h1>内容加载完成!</h1>}
</div>
)
}
export default App
解释:
- 初始状态
loading = true
,渲染Loading
组件。 useEffect
模拟 API 请求,3 秒后setLoading(false)
,隐藏Loading
,显示h1
内容。
方法 2:使用 className
控制 Loading
组件隐藏
如果 Loading
组件在某个页面或组件中是 固定的,可以用 className
让它淡出或隐藏。
修改 Loading
组件
const Loading = ({ type = 'area', visible = true }: ILoadingProps & { visible?: boolean }) => {
return (
<div className={`flex w-full justify-center items-center transition-opacity duration-500 ${type === 'app' ? 'h-full' : ''} ${visible ? 'opacity-100' : 'opacity-0 pointer-events-none'}`}>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className='spin-animation'>
<g clipPath="url(#clip0_324_2488)">
<path d="M15 0H10C9.44772 0 9 0.447715 9 1V6C9 6.55228 9.44772 7 10 7H15C15.5523 7 16 6.55228 16 6V1C16 0.447715 15.5523 0 15 0Z" fill="#1C64F2" />
</g>
</svg>
</div>
)
}
在父组件中
const App = () => {
const [loading, setLoading] = useState(true)
useEffect(() => {
setTimeout(() => {
setLoading(false)
}, 3000)
}, [])
return (
<div>
<Loading type="app" visible={loading} />
<h1 className={`${loading ? 'hidden' : 'block'}`}>内容加载完成!</h1>
</div>
)
}
解释:
visible
通过className
控制Loading
的opacity
,实现 淡出动画。hidden/block
控制h1
在加载完成后才显示。
方法 3:完全移除 Loading
组件
如果不想使用 className
过渡,而是 彻底移除 Loading
组件,可以这样写:
const App = () => {
const [loading, setLoading] = useState(true)
useEffect(() => {
setTimeout(() => {
setLoading(false)
}, 3000)
}, [])
return (
<div>
{loading && <Loading type="app" />}
{!loading && <h1>内容加载完成!</h1>}
</div>
)
}
效果:
loading === true
时,渲染<Loading />
。loading === false
时,直接 删除<Loading />
,只显示内容。
总结
方法 | 适用场景 | 说明 |
---|---|---|
useState 控制 Loading 组件是否渲染 |
简单,适用于数据加载时 | loading ? <Loading /> : <内容> |
className 控制 opacity |
需要 淡出动画 | opacity-100 → opacity-0 过渡 |
完全移除 Loading 组件 |
只需简单地 显示/隐藏 | loading && <Loading /> |
如果你希望 加载动画消失得更自然,推荐 方法 2(opacity
过渡动画)。