React之Loading组件

半兽人 发表于: 2025-03-18   最后更新时间: 2025-03-18 15:16:33  
{{totalSubscript}} 订阅, 46 游览

这是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 控制 Loadingopacity,实现 淡出动画
  • 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-100opacity-0 过渡
完全移除 Loading 组件 只需简单地 显示/隐藏 loading && <Loading />

如果你希望 加载动画消失得更自然,推荐 方法 2opacity 过渡动画)。

更新于 2025-03-18
在线,1小时前登录

查看React更多相关的文章或提一个关于React的问题,也可以与我们一起分享文章