这是一个来自谷歌Adsense应用页面的例子。加载界面显示在主界面之前。

我不知道如何用React做同样的事情,因为如果我用React组件渲染加载屏幕,它不会在页面加载时显示,因为它必须等待DOM渲染之前。

更新:

我通过将屏幕加载器放在index.html中并在React componentDidMount()生命周期方法中删除它来举例说明我的方法。

示例和反应加载屏幕。


当前回答

你不需要那么多的努力,这里有一个基本的例子。

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

<head>
  <meta charset="utf-8" />
  <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="theme-color" content="#000000" />
  <meta name="description" content="Web site created using create-react-app" />
  <link rel="apple-touch-icon" href="logo192.png" />
  <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
  <title>Title</title>
  <style>
    body {
      margin: 0;
    }

    .loader-container {
      width: 100vw;
      height: 100vh;
      display: flex;
      overflow: hidden;
    }

    .loader {
      margin: auto;
      border: 5px dotted #dadada;
      border-top: 5px solid #3498db;
      border-radius: 50%;
      width: 100px;
      height: 100px;
      -webkit-animation: spin 2s linear infinite;
      animation: spin 2s linear infinite;
    }

    @-webkit-keyframes spin {
      0% {
        -webkit-transform: rotate(0deg);
      }

      100% {
        -webkit-transform: rotate(360deg);
      }
    }

    @keyframes spin {
      0% {
        transform: rotate(0deg);
      }

      100% {
        transform: rotate(360deg);
      }
    }

  </style>
</head>

<body>
  <noscript>You need to enable JavaScript to run this app.</noscript>
  <div id="root">
    <div class="loader-container">
      <div class="loader"></div>
    </div>
  </div>
</body>

</html>

您可以使用HTML和CSS使其看起来像您的示例。

其他回答

解决这个问题的方法是在你的渲染函数中这样做:

constructor() {
    this.state = { isLoading: true }
}

componentDidMount() {
    this.setState({isLoading: false})
}

render() {
    return(
        this.state.isLoading ? *showLoadingScreen* : *yourPage()*
    )
}

在构造函数中将isLoading初始化为true,在componentDidMount上将其初始化为false。

这将发生在ReactDOM.render()控制根目录<div>之前。也就是说,你的应用程序到那时还没有被安装。

所以你可以把你的加载器添加到index.html文件的根目录<div>。在React接管之前,这将在屏幕上可见。

您可以使用任何最适合您的加载器元素(例如带有动画的svg)。

您不需要在任何生命周期方法上删除它。React会用你渲染的<App/>替换它的根<div>的所有子元素,就像我们在下面的动图中看到的那样。

关于CodeSandbox的例子

index . html

<head>
  <style>
    .svgLoader {
      animation: spin 0.5s linear infinite;
      margin: auto;
    }
    .divLoader {
      width: 100vw;
      height: 100vh;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    @keyframes spin {
      0% { transform: rotate(0deg); }
      100% { transform: rotate(360deg); }
    }
  </style>
</head>

<body>
  <div id="root">
    <div class="divLoader">
      <svg class="svgLoader" viewBox="0 0 1024 1024" width="10em" height="10em">
        <path fill="lightblue"
          d="PATH FOR THE LOADER ICON"
        />
      </svg>
    </div>
  </div>
</body>

index.js

在ReactDOM.render()运行之前,使用调试器检查页面。

import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";

function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

debugger; // TO INSPECT THE PAGE BEFORE 1ST RENDER

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

如果有人正在为上述用例寻找一个插入式、零配置和零依赖的库,请尝试pace.js (https://codebyzach.github.io/pace/docs/)。

它自动挂钩事件(ajax, readyState,历史推送状态,js事件循环等),并显示一个可定制的加载器。

与我们的react/relay项目合作良好(使用react-router, relay请求处理导航更改) (不是affliated;在我们的项目中使用了pace.js,它工作得很好)

我也在我的应用程序中使用React。对于请求,我使用axios拦截器,所以让加载器屏幕的好方法(fullpage,因为你展示了一个例子)是在拦截器内部添加类或id为例(这里的代码来自官方文档,一些自定义代码):

// Add a request interceptor
axios.interceptors.request.use(function (config) {
    // Do something before request is sent
     document.body.classList.add('custom-loader');
     return config;
  }, function (error) {
    // Do something with request error
    return Promise.reject(error);
  });

// Add a response interceptor
axios.interceptors.response.use(function (response) {
    // Do something with response data
       document.body.classList.remove('custom-loader');
       return response;
  }, function (error) {
    // Do something with response error
    return Promise.reject(error);
  }); 

然后在CSS中使用伪元素实现你的加载器(或添加类或id到不同的元素,而不是你喜欢的body) -你可以设置背景的颜色为不透明或透明,等等…例子:

custom-loader:before {
    background: #000000;
    content: "";
    position: fixed;
    ...
}

custom-loader:after {
    background: #000000;
    content: "Loading content...";
    position: fixed;
    color: white;
    ...
}

当你的React应用程序是巨大的,它真的需要时间来启动和运行后,页面已经加载。比如,你将应用的React部分挂载到#app上。通常,index.html中的这个元素只是一个空的div:

<div id="app"></div>

你可以做的是放一些样式和一堆图像,让它在页面加载和初始React应用程序渲染到DOM之间看起来更好:

<div id="app">
  <div class="logo">
    <img src="/my/cool/examplelogo.svg" />
  </div>
  <div class="preload-title">
    Hold on, it's loading!
  </div>
</div>

页面加载后,用户将立即看到index.html的原始内容。不久之后,当React准备好将呈现的组件的整个层次结构挂载到这个DOM节点时,用户将看到实际的应用程序。

注意class,而不是className。这是因为你需要把它放到html文件中。


如果你使用SSR,事情就不那么复杂了,因为用户会在页面加载后立即看到真正的应用程序。