React页面加载动画

364 阅读1分钟

页面加载动画

说明

动画的开启与关闭都是可控的。

设计

思路

使用闭包思想,实现单例模式(导入后无论是多次开启或关闭都是对同一个加载框进行操作)

代码

  1. 先实现模板

    const Loading = ({ status = false }: { status: boolean }) => {
        // 使用传入的 status 管理加载页面是否生成
      return (
        <div className={styles.loading}>
          {status ? (
            <>
              <div className={styles.txt}>LOADING</div>
              <div className={styles.ring}></div>
            </>
          ) : null}
        </div>
      )
    }
    
    .loading{
        position: fixed;
        left: 50%;
        top: 50%;
    ​
        .txt,
        .ring{
            position: fixed;
            width: 120px;
            height: 120px;
            text-align: center;
            line-height: 120px;
            border-radius: 50%;
            font-size: 20px;
            
        }
        .ring{
            box-shadow: 4px 0 0 0 #6dce70; 
            animation: loading 1s linear infinite;
    ​
        }
    }
    ​
    @keyframes loading {
        0%{
            transform: rotateZ(0);
        }
        100%{
            transform: rotateZ(360deg);
        }
    }
    
  2. 实现闭包并导出所需要的函数

    export const Load = (function () {
      let containerRoot: any = null
    ​
      // 创建根容器
      const createContainer = () => {
        if (containerRoot) {
          return containerRoot
        }
        const div = document.createElement('div')
        document.body.appendChild(div)
        const container = createRoot(div)
    ​
        return container
      }
    ​
      // 渲染Loading动画
      const render = (status: boolean) => {
        containerRoot.render(<Loading status={status}></Loading>)
      }
    ​
      return {
        open: () => {
          containerRoot = createContainer()
          render(true)
        },
        close: () => {
          if (!containerRoot) {
            throw new Error('您应该先开启一个后才可以关闭')
          }
          render(false)
        },
      }
    })()
    

测试

import { Load } from '../../UI/Loading/Loading'const TestLoading = () => {
  return (
    <div>
      <button onClick={Load.open}>开启动画</button>
      <button onClick={Load.close}>关闭动画</button>
    </div>
  )
}
​
export default TestLoading

题外话

在做了几个组建后,我发现对于这些只需要创建一次的组件(全局通知、加载动画...),我们都可以使用单例来创建一个全局容器,然后一直使用这个容器,我们不需要加载一次组件就创建一个容器,性能太差

GitHub源码地址

也欢迎到 我的网站 查看