gpt4 book ai didi

reactjs - React - 在 DOM 渲染时显示加载屏幕?

转载 作者:行者123 更新时间:2023-12-03 12:53:04 25 4
gpt4 key购买 nike

这是 Google AdSense 申请页面的示例。在显示主页之前显示加载屏幕。

enter image description here

我不确定如何使用 React 实现相同的效果,因为如果我将加载屏幕渲染为 React 组件,则在页面加载时它不会显示,因为它需要等待 DOM 首先渲染。

更新:

作为解决方案,我尝试了一种方法,将屏幕加载器放置在 index.html 文件中,并在 React 组件的 componentDidMount() 生命周期方法中将其删除。

Examplereact-loading-screen .

最佳答案

目标

当 html 页面渲染时,立即显示一个旋转器(React 加载时),并在 React 准备好后隐藏它。

由于微调器是用纯 HTML/CSS 渲染的(在 React 域之外),React 不应该直接控制显示/隐藏过程,并且实现对 React 应该是透明的。

解决方案 1 - :empty 伪类

由于您将 React 渲染到 DOM 容器中 - <div id="app"></div> ,您可以向该容器添加一个微调器,当 React 加载并渲染时,微调器将会消失。

你不能在react root中添加DOM元素(例如div),因为React将在ReactDOM.render()后立即替换容器的内容。叫做。即使你渲染null ,内容仍会被评论替换 - <!-- react-empty: 1 --> 。这意味着,如果您想在安装主组件、正在加载数据时显示加载程序,但实际上没有渲染任何内容,则放置在容器内的加载程序标记(例如 <div id="app"><div class="loader"></div></div>)将不起作用。

解决方法是将 spinner 类添加到 React 容器中,并使用 :empty pseudo class 。只要容器中没有渲染任何内容,微调器就会可见(注释不计在内)。一旦 React 呈现除注释以外的内容,加载器就会消失。

示例 1

在示例中,您可以看到一个渲染 null 的组件直到准备好。容器也是装载机 - <div id="app" class="app"></div> ,并且加载器的类仅在 :empty 时才起作用。 (参见代码中的注释):

class App extends React.Component {
state = {
loading: true
};

componentDidMount() {
// this simulates an async action, after which the component will render the content
demoAsyncCall().then(() => this.setState({ loading: false }));
}

render() {
const { loading } = this.state;

if(loading) { // if your component doesn't have to wait for an async action, remove this block
return null; // render null when app is not ready
}

return (
<div>I'm the app</div>
);
}
}

function demoAsyncCall() {
return new Promise((resolve) => setTimeout(() => resolve(), 2500));
}

ReactDOM.render(
<App />,
document.getElementById('app')
);
.loader:empty {
position: absolute;
top: calc(50% - 4em);
left: calc(50% - 4em);
width: 6em;
height: 6em;
border: 1.1em solid rgba(0, 0, 0, 0.2);
border-left: 1.1em solid #000000;
border-radius: 50%;
animation: load8 1.1s infinite linear;
}

@keyframes load8 {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react-dom.js"></script>

<div id="app" class="loader"></div> <!-- add class loader to container -->

示例 2

使用 :empty 的变体显示/隐藏选择器的伪类,将微调器设置为应用程序容器的同级元素,并使用 adjacent sibling combinator 在容器为空时显示它(+):

class App extends React.Component {
state = {
loading: true
};

componentDidMount() {
// this simulates an async action, after which the component will render the content
demoAsyncCall().then(() => this.setState({ loading: false }));
}

render() {
const { loading } = this.state;

if(loading) { // if your component doesn't have to wait for async data, remove this block
return null; // render null when app is not ready
}

return (
<div>I'm the app</div>
);
}
}

function demoAsyncCall() {
return new Promise((resolve) => setTimeout(() => resolve(), 2500));
}

ReactDOM.render(
<App />,
document.getElementById('app')
);
#app:not(:empty) + .sk-cube-grid {
display: none;
}

.sk-cube-grid {
width: 40px;
height: 40px;
margin: 100px auto;
}

.sk-cube-grid .sk-cube {
width: 33%;
height: 33%;
background-color: #333;
float: left;
animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out;
}

.sk-cube-grid .sk-cube1 {
animation-delay: 0.2s;
}

.sk-cube-grid .sk-cube2 {
animation-delay: 0.3s;
}

.sk-cube-grid .sk-cube3 {
animation-delay: 0.4s;
}

.sk-cube-grid .sk-cube4 {
animation-delay: 0.1s;
}

.sk-cube-grid .sk-cube5 {
animation-delay: 0.2s;
}

.sk-cube-grid .sk-cube6 {
animation-delay: 0.3s;
}

.sk-cube-grid .sk-cube7 {
animation-delay: 0s;
}

.sk-cube-grid .sk-cube8 {
animation-delay: 0.1s;
}

.sk-cube-grid .sk-cube9 {
animation-delay: 0.2s;
}

@keyframes sk-cubeGridScaleDelay {
0%,
70%,
100% {
transform: scale3D(1, 1, 1);
}
35% {
transform: scale3D(0, 0, 1);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react-dom.js"></script>

<div id="app"></div>
<!-- add class loader to container -->

<div class="sk-cube-grid">
<div class="sk-cube sk-cube1"></div>
<div class="sk-cube sk-cube2"></div>
<div class="sk-cube sk-cube3"></div>
<div class="sk-cube sk-cube4"></div>
<div class="sk-cube sk-cube5"></div>
<div class="sk-cube sk-cube6"></div>
<div class="sk-cube sk-cube7"></div>
<div class="sk-cube sk-cube8"></div>
<div class="sk-cube sk-cube9"></div>
</div>

<小时/>

解决方案 2 - 将微调器“处理程序”作为 props 传递

要对微调器显示状态进行更细粒度的控制,请创建两个函数 showSpinnerhideSpinner ,并通过 props 将它们传递给根容器。这些函数可以操作 DOM,或者执行控制微调器所需的任何操作。这样,React 就感知不到“外部世界”,也不需要直接控制 DOM。您可以轻松替换函数进行测试,或者如果您需要更改逻辑,您可以将它们传递给React树中的其他组件。

示例 1

const loader = document.querySelector('.loader');

// if you want to show the loader when React loads data again
const showLoader = () => loader.classList.remove('loader--hide');

const hideLoader = () => loader.classList.add('loader--hide');

class App extends React.Component {
componentDidMount() {
this.props.hideLoader();
}

render() {
return (
<div>I'm the app</div>
);
}
}

// the setTimeout simulates the time it takes react to load, and is not part of the solution
setTimeout(() =>
// the show/hide functions are passed as props
ReactDOM.render(
<App
hideLoader={hideLoader}
showLoader={showLoader}
/>,
document.getElementById('app')
)
, 1000);
.loader {
position: absolute;
top: calc(50% - 4em);
left: calc(50% - 4em);
width: 6em;
height: 6em;
border: 1.1em solid rgba(0, 0, 0, 0.2);
border-left: 1.1em solid #000000;
border-radius: 50%;
animation: load8 1.1s infinite linear;
transition: opacity 0.3s;
}

.loader--hide {
opacity: 0;
}

@keyframes load8 {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react-dom.js"></script>

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

<div class="loader"></div>

示例 2 - Hook

此示例使用 useEffect 组件安装后隐藏微调器的钩子(Hook)。

const { useEffect } = React;

const loader = document.querySelector('.loader');

// if you want to show the loader when React loads data again
const showLoader = () => loader.classList.remove('loader--hide');

const hideLoader = () => loader.classList.add('loader--hide');

const App = ({ hideLoader }) => {
useEffect(hideLoader, []);

return (
<div>I'm the app</div>
);
}

// the setTimeout simulates the time it takes react to load, and is not part of the solution
setTimeout(() =>
// the show/hide functions are passed as props
ReactDOM.render(
<App
hideLoader={hideLoader}
showLoader={showLoader}
/>,
document.getElementById('app')
)
, 1000);
.loader {
position: absolute;
top: calc(50% - 4em);
left: calc(50% - 4em);
width: 6em;
height: 6em;
border: 1.1em solid rgba(0, 0, 0, 0.2);
border-left: 1.1em solid #000000;
border-radius: 50%;
animation: load8 1.1s infinite linear;
transition: opacity 0.3s;
}

.loader--hide {
opacity: 0;
}

@keyframes load8 {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

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

<div class="loader"></div>

关于reactjs - React - 在 DOM 渲染时显示加载屏幕?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40987309/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com