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

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

更新:

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

示例和反应加载屏幕。


当前回答

我最近不得不处理这个问题,并想出了一个解决方案,这对我来说很好。然而,我已经尝试了上面的@Ori Drori解决方案,不幸的是,它并没有正确工作(有一些延迟+我不喜欢setTimeout函数的使用)。

这是我想到的:

index . html文件

内头标签-指示器的样式:

<style media="screen" type="text/css">

.loading {
  -webkit-animation: sk-scaleout 1.0s infinite ease-in-out;
  animation: sk-scaleout 1.0s infinite ease-in-out;
  background-color: black;
  border-radius: 100%;
  height: 6em;
  width: 6em;
}

.container {
  align-items: center;
  background-color: white;
  display: flex;
  height: 100vh;
  justify-content: center;
  width: 100vw;
}

@keyframes sk-scaleout {
  0% {
    -webkit-transform: scale(0);
    transform: scale(0);
  }
  100% {
    -webkit-transform: scale(1.0);
    opacity: 0;
    transform: scale(1.0);
  }
}

</style>

现在是body标签:

<div id="spinner" class="container">
  <div class="loading"></div>
</div>

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

然后是一个非常简单的逻辑,在app.js文件中(在渲染函数中):

const spinner = document.getElementById('spinner');

if (spinner && !spinner.hasAttribute('hidden')) {
  spinner.setAttribute('hidden', 'true');
}

它是如何工作的?

当第一个组件(在我的应用程序中,大多数情况下是app.js)正确安装时,旋转器将被隐藏,并应用隐藏属性给它。

更重要的是补充什么- spinner. hasattribute ('hidden')条件阻止在每次组件挂载时向spinner添加隐藏属性,因此实际上它只会在整个应用程序加载时添加一次。

其他回答

当你的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,事情就不那么复杂了,因为用户会在页面加载后立即看到真正的应用程序。

我也在我的应用程序中使用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的lazy特性轻松解决。

import { Suspense, lazy } from "react"
import Loading from "components/Loading"

const Dashboard = lazy(() => import("containers/Dashboard"))

const App = () => (
  <Suspense fallback={<Loading />}>
    <Dashboard />
  </Suspense>
)

export default App

当仪表板组件仍在加载时,加载组件将显示出来。

最重要的问题是:“loading”是什么意思?如果你谈论的是被安装的物理元素,这里的一些第一个答案很好。然而,如果你的应用做的第一件事是检查身份验证,你真正加载的是来自后端的数据,用户是否传递了一个cookie,标签他们是授权或未授权的用户。

这是基于redux的,但你可以很容易地将其更改为普通的反应状态模型。

行动的创造者:

export const getTodos = () => {
  return async dispatch => {
    let res;
    try {
      res = await axios.get('/todos/get');

      dispatch({
        type: AUTH,
        auth: true
      });
      dispatch({
        type: GET_TODOS,
        todos: res.data.todos
      });
    } catch (e) {
    } finally {
      dispatch({
        type: LOADING,
        loading: false
      });
    }
  };
};

最后一部分意味着无论用户是否被授权,在收到响应后加载屏幕都会消失。

下面是加载它的组件的样子:

class App extends Component {
  renderLayout() {
    const {
      loading,
      auth,
      username,
      error,
      handleSidebarClick,
      handleCloseModal
    } = this.props;
    if (loading) {
      return <Loading />;
    }
    return (
      ...
    );
  }

  ...

  componentDidMount() {
    this.props.getTodos();
  }

...

  render() {
    return this.renderLayout();
 }

}

如果状态。加载是真实的,我们总是会看到加载屏幕。在componentDidMount上,我们调用getTodos函数,它是一个转换状态的动作创建器。当我们得到一个响应(这可能是一个错误)加载假。我们的组件更新,再次调用渲染,这一次没有加载屏幕,因为if语句。

现在我们也可以在React 16.8中使用钩子:

import React, { useState, useEffect } from 'react';

const App = () => {
  const [ spinner, setSpinner ] = useState(true);

  // It will be executed before rendering

  useEffect(() => {
    setTimeout(() => setSpinner(false), 1000)
  }, []);

  // [] means like componentDidMount

  return !spinner && <div>Your content</div>;
};

export default App;