这是一个来自谷歌Adsense应用页面的例子。加载界面显示在主界面之前。
我不知道如何用React做同样的事情,因为如果我用React组件渲染加载屏幕,它不会在页面加载时显示,因为它必须等待DOM渲染之前。
更新:
我通过将屏幕加载器放在index.html中并在React componentDidMount()生命周期方法中删除它来举例说明我的方法。
示例和反应加载屏幕。
这是一个来自谷歌Adsense应用页面的例子。加载界面显示在主界面之前。
我不知道如何用React做同样的事情,因为如果我用React组件渲染加载屏幕,它不会在页面加载时显示,因为它必须等待DOM渲染之前。
更新:
我通过将屏幕加载器放在index.html中并在React componentDidMount()生命周期方法中删除它来举例说明我的方法。
示例和反应加载屏幕。
当前回答
在componentDidMount中设置超时工作,但在我的应用程序中,我收到了内存泄漏警告。试试这样的方法。
constructor(props) {
super(props)
this.state = {
loading: true,
}
}
componentDidMount() {
this.timerHandle = setTimeout(() => this.setState({ loading: false }), 3500);
}
componentWillUnmount(){
if (this.timerHandle) {
clearTimeout(this.timerHandle);
this.timerHandle = 0;
}
}
其他回答
当你的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,事情就不那么复杂了,因为用户会在页面加载后立即看到真正的应用程序。
我最近不得不处理这个问题,并想出了一个解决方案,这对我来说很好。然而,我已经尝试了上面的@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添加隐藏属性,因此实际上它只会在整个应用程序加载时添加一次。
在componentDidMount中设置超时工作,但在我的应用程序中,我收到了内存泄漏警告。试试这样的方法。
constructor(props) {
super(props)
this.state = {
loading: true,
}
}
componentDidMount() {
this.timerHandle = setTimeout(() => this.setState({ loading: false }), 3500);
}
componentWillUnmount(){
if (this.timerHandle) {
clearTimeout(this.timerHandle);
this.timerHandle = 0;
}
}
现在我们也可以在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;
最重要的问题是:“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语句。