Reagieren - Ladebildschirm anzeigen, während DOM gerendert wird?

147

Dies ist ein Beispiel von der Google Adsense-Anwendungsseite. Der Ladebildschirm, der vor der Hauptseite angezeigt wird, wird nach angezeigt.

Geben Sie hier die Bildbeschreibung ein

Ich weiß nicht, wie ich mit React dasselbe machen soll, denn wenn ich einen von der React-Komponente gerenderten Ladebildschirm erstelle, wird dieser beim Laden der Seite nicht angezeigt, da zuvor auf das gerenderte DOM gewartet werden muss.

Aktualisiert :

Ich habe ein Beispiel für meinen Ansatz gemacht, indem ich Screen Loader eingesetzt index.htmlund in der React componentDidMount()Lifecycle-Methode entfernt habe.

Beispiel und React-Loading-Screen .

Thanh Nguyen
quelle
Zeigen Sie, was Sie in einfachen js anzeigen möchten, und machen Sie es dann ausgeblendet oder entfernen Sie es aus dem DOM, wenn die Reaktion aktiviert wurde. Alles was Sie tun müssen, ist es vor dem Reaktionscode zu verbergen.
FurkanO
Das ist einfach wunderbar! Danke dir.
Arman Karimi

Antworten:

100

Dies kann durch Platzieren des Ladesymbols in Ihrer HTML-Datei (z. B. index.html) erfolgen, sodass Benutzer das Symbol unmittelbar nach dem Laden der HTML-Datei sehen.

Wenn Ihre App fertig geladen ist, können Sie das Ladesymbol einfach in einem Lifecycle-Hook entfernen. Normalerweise mache ich das in componentDidMount.

kkkkkkk
quelle
11
Wenn Sie die Stammkomponente auf dem übergeordneten Knoten dieses Symbols bereitstellen, müssen Sie sie nicht einmal manuell entfernen. React bereinigt untergeordnete Elemente des Mount-Knotens und legt stattdessen dort ein eigenes neu gerendertes DOM ab.
Rishat
6
Ich habe das Symbol nicht in den
Stammknoten
169

Das Ziel

Wenn die HTML-Seite gerendert wird, zeigen Sie sofort einen Drehfeld an (während React geladen wird) und blenden Sie ihn aus, nachdem React fertig ist.

Da der Spinner in reinem HTML / CSS (außerhalb der React-Domäne) gerendert wird, sollte React den Ein- / Ausblendungsprozess nicht direkt steuern und die Implementierung sollte für React transparent sein.

Lösung 1 - die: leere Pseudoklasse

Da Sie die Reaktion in einen DOM-Container rendern <div id="app"></div>, können Sie diesem Container einen Spinner hinzufügen. Wenn die Reaktion geladen und gerendert wird, verschwindet der Spinner.

Sie können kein DOM-Element (z. B. ein div) in die React-Wurzel einfügen, da React den Inhalt des Containers ersetzt, sobald ReactDOM.render()es aufgerufen wird. Selbst wenn Sie rendern null, wird der Inhalt durch einen Kommentar ersetzt - <!-- react-empty: 1 -->. Dies bedeutet, dass, wenn Sie den Loader anzeigen möchten, während die Hauptkomponente bereitgestellt wird, Daten geladen werden, aber tatsächlich nichts gerendert wird, ein im Container platziertes Loader-Markup ( <div id="app"><div class="loader"></div></div>zum Beispiel) nicht funktioniert.

Eine Abhilfe ist , die Spinner - Klasse die reagieren Behälter, aufzuwerten und die Verwendung :emptyPseudo - Klasse . Der Spinner ist sichtbar, solange nichts in den Container gerendert wird (Kommentare zählen nicht). Sobald die Reaktion etwas anderes als einen Kommentar wiedergibt, verschwindet der Lader.

Beispiel 1

Im Beispiel sehen Sie eine Komponente, die gerendert wird, nullbis sie fertig ist. Der Container ist auch der Loader - <div id="app" class="app"></div>und die Klasse des Loaders funktioniert nur, wenn dies der Fall ist :empty(siehe Kommentare im Code):

Beispiel 2

Eine Variation der Verwendung der :emptyPseudoklasse zum Ein- / Ausblenden eines Selektors besteht darin, den Spinner als Geschwisterelement für den App-Container festzulegen und ihn anzuzeigen, solange der Container mit dem benachbarten Geschwisterkombinator leer ist ( +):


Lösung 2 - Übergeben Sie Spinner "Handler" als Requisiten

Um den Anzeigezustand der Spinner genauer steuern zu können, erstellen Sie zwei Funktionen showSpinnerund hideSpinnerund übergeben Sie sie über Requisiten an den Root-Container. Die Funktionen können das DOM manipulieren oder alles tun, um den Spinner zu steuern. Auf diese Weise ist sich React weder der "Außenwelt" bewusst, noch muss das DOM direkt gesteuert werden. Sie können die Funktionen zum Testen oder zum Ändern der Logik einfach ersetzen und an andere Komponenten im Reaktionsbaum übergeben.

Beispiel 1

Beispiel 2 - Haken

In diesem Beispiel wird der useEffectSpinner nach dem Einhängen der Komponente mithilfe des Hakens ausgeblendet.

Ori Drori
quelle
Können Sie klarstellen, wo sich die letzten beiden Codeabschnitte befinden sollten? Die erste befindet sich eindeutig in der Javascript-src-Datei für die Reaktionskomponente, die dritte befindet sich vermutlich in der HTML-Vorlage, die von der js-Datei gerendert werden soll, aber wohin geht die zweite?
Levraininjaneer
1
Das zweite ist das CSS. Ich habe globales CSS verwendet, aber Sie können CSS-Module oder CSS in JS verwenden. Die dritte ist die HTML-Datei, die bei Bedarf ein Spinner-Markup enthalten kann (zweites Beispiel).
Ori Drori
Dieses Timeout ist nicht gut, wenn die Leistung berücksichtigt wird.
Dryleaf
4
@dryleaf - das setTimeout ist nicht Teil der Lösung. Es simuliert das Warten auf eine asynchrone Aktion, bevor der Inhalt gerendert wird.
Ori Drori
Ich benutze einen ähnlichen Ansatz. Ich kann im Webpack nichts finden, was mir helfen könnte, den für den Loader erforderlichen Cache für die CSS-Datei zu sprengen. Kannst du helfen?
Hamza-Jutt
40

Die Problemumgehung hierfür ist:

Gehen Sie in Ihrer Renderfunktion folgendermaßen vor:

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

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

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

Initialisieren Sie isLoading im Konstruktor als true und in componentDidMount als false

Amoolya S Kumar
quelle
Wenn wir die Ajax-Methode aufgerufen haben, um Daten in die untergeordneten Komponenten zu laden. componentDidMount wird aufgerufen, bevor untergeordnete Komponentendaten gefüllt werden. Wie überwinden wir diese Art von Problem?
dush88c
2
Für Mounting Life Cyle ist es in Ordnung, möchten Sie etwas für den Aktualisierungslebenszyklus hinzufügen?
Zakir
Muss ich das auf allen Seiten oder nur im App-Eintrag tun
Pedro JR
16

Wenn Sie nach einer Drop-In-, Zero-Config- und Zero-Dependencies-Bibliothek für den oben genannten Anwendungsfall suchen, versuchen Sie es mit schritt.js ( http://github.hubspot.com/pace/docs/welcome/ ).

Es verbindet sich automatisch mit Ereignissen (Ajax, ReadyState, Verlaufs-Pushstate, JS-Ereignisschleife usw.) und zeigt einen anpassbaren Loader an.

Funktionierte gut mit unseren React / Relay-Projekten (behandelt Navigationsänderungen mit React -Router, Relay-Anfragen) (Nicht verbunden; hatte tempo.js für unsere Projekte verwendet und es hat großartig funktioniert)

Hafiz Ismail
quelle
Hallo! Kannst du mir sagen, wie man es mit Reagieren benutzt?
uneet7
Hängen Sie einfach das Skript an public/index.htmlund wählen Sie einen Stil. Das ist ganz einfach, tolles Plugin. Danke.
PJ3
Ohne diese Antwort hätte ich kein Tempo gefunden. Es war so einfach einzuschließen, und mit ein wenig CSS-Magie und einigen Ereignisanhängen konnte ich die App während der Übergänge blockieren / deaktivieren und den Spinner anpassen.
invertedSpear
12

Wenn Ihre React-App sehr umfangreich ist, dauert es wirklich einige Zeit, bis sie nach dem Laden der Seite betriebsbereit ist. Angenommen, Sie mounten Ihren React-Teil der App an #app. Normalerweise ist dieses Element in Ihrer index.html einfach ein leeres div:

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

Sie können stattdessen etwas Styling und eine Reihe von Bildern hinzufügen, damit es zwischen dem Laden der Seite und dem ersten Rendern der React-App in DOM besser aussieht:

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

Nach dem Laden der Seite wird dem Benutzer sofort der ursprüngliche Inhalt von index.html angezeigt. Kurz danach, wenn React bereit ist, die gesamte Hierarchie der gerenderten Komponenten in diesen DOM-Knoten einzubinden, wird dem Benutzer die eigentliche App angezeigt.

Beachten Sie classnicht className. Das liegt daran, dass Sie dies in Ihre HTML-Datei einfügen müssen.


Wenn Sie SSR verwenden, sind die Dinge weniger kompliziert, da der Benutzer die echte App direkt nach dem Laden der Seite sieht.

Rishat
quelle
Dies funktioniert auch ich habe zwei Stellen, an denen das Laden stattfindet. Eines ist die massive App. und als nächstes kommt die Vorbereitung (Montage verschiedener Komponenten). Ich bekomme also einen blinkenden Schritt, weil die app.render übernimmt und die Animation zurückgesetzt wird ( wirklich ersetzt ). Gibt es eine Möglichkeit, diesen Blitz zu vermeiden? Wird React das DOM eins zu eins vergleichen? Aber soweit ich weiß, fügt React alle möglichen privaten Daten in die Tags ein ...
Alexis Wilke
12

Dies geschieht, bevor ReactDOM.render()die Kontrolle über die Wurzel übernommen wird <div> . Dh Ihre App wurde bis zu diesem Zeitpunkt noch nicht gemountet.

So können Sie Ihren Loader in Ihre index.htmlDatei im Stammverzeichnis einfügen <div>. Und das wird auf dem Bildschirm sichtbar sein, bis React übernimmt.

Sie können jedes Loader-Element verwenden, das für Sie am besten geeignet ist ( svgz. B. mit Animation).

Sie müssen es bei keiner Lebenszyklusmethode entfernen. React ersetzt alle Kinder seiner Wurzel <div> durch Ihre gerenderten <App/>, wie wir im GIF unten sehen können.

Beispiel für CodeSandbox

Geben Sie hier die Bildbeschreibung ein

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

Verwenden Sie debuggerdiese Option, um die Seite vor dem Ausführen zu überprüfen 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);
Entwickler
quelle
eine schöne und elegante Lösung
Gal Margalit
1
Ich bin froh, dass es hilft!
Entwickler
9

Heutzutage können wir in React 16.8 auch Hooks verwenden:

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;
Max Kalik
quelle
5

Das Festlegen des Zeitlimits in componentDidMount funktioniert, aber in meiner Anwendung wurde eine Warnung zum Speicherverlust angezeigt. Versuchen Sie so etwas.

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;
    }
  }
Rich Costello
quelle
4

Ich musste mich kürzlich mit diesem Problem befassen und fand eine Lösung, die für mich gut funktioniert. Allerdings habe ich oben die @ Ori Drori-Lösung ausprobiert und leider hat sie nicht richtig funktioniert (hatte einige Verzögerungen + Ich mag die Verwendung der setTimeoutFunktion dort nicht).

Folgendes habe ich mir ausgedacht:

index.html Datei

Inside head Tag - Stile für den Indikator:

<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>

Nun das bodyTag:

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

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

Und dann kommt eine sehr einfache Logik innerhalb der app.jsDatei (in der Renderfunktion):

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

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

Wie funktioniert es

Wenn die erste Komponente (in meiner App app.jsin den meisten Fällen auch) korrekt bereitgestellt wird, spinnerwird sie durch Anwenden eines hiddenAttributs ausgeblendet .

Was ist wichtiger hinzuzufügen - !spinner.hasAttribute('hidden')Bedingung verhindert, dass hiddendem Spinner bei jedem Komponenten-Mount ein Attribut hinzugefügt wird, sodass es tatsächlich nur einmal hinzugefügt wird, wenn die gesamte App geladen wird.

freundlicher Benutzer
quelle
4

Ich verwende das Paket react-progress-2 npm, das keine Abhängigkeit aufweist und in ReactJS hervorragend funktioniert.

https://github.com/milworm/react-progress-2

Installation:

npm install react-progress-2

Fügen Sie Ihrem Projekt react-progress-2 / main.css hinzu.

import "node_modules/react-progress-2/main.css";

Fügen Sie es ein react-progress-2und platzieren Sie es irgendwo in der obersten Komponente, zum Beispiel:

import React from "react";
import Progress from "react-progress-2";

var Layout = React.createClass({
render: function() {
    return (
        <div className="layout">
            <Progress.Component/>
                {/* other components go here*/}
            </div>
        );
    }
});

Wenn Sie jetzt einen Indikator anzeigen müssen, rufen Sie einfach an Progress.show(), zum Beispiel:

loadFeed: function() {
    Progress.show();
    // do your ajax thing.
},

onLoadFeedCallback: function() {
    Progress.hide();
    // render feed.
}

Bitte beachten Sie, dass showund hideAnrufe gestapelt sind. Nach n aufeinanderfolgenden Show-Anrufen müssen Sie n Anrufe ausblenden, um einen Indikator auszublenden, oder Sie können verwenden Progress.hideAll().

Alex Zavrazhniy
quelle
4

Ich verwende auch React in meiner App. Für Anfragen, bei denen ich Axios-Interceptors verwende, ist es eine gute Möglichkeit, den Loader-Bildschirm (ganzseitig, wie Sie ein Beispiel gezeigt haben) zu erstellen, Klasse oder ID beispielsweise zum Body innerhalb von Interceptors hinzuzufügen (hier Code aus der offiziellen Dokumentation mit einem benutzerdefinierten Code):

// 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);
  }); 

Und dann implementieren Sie einfach in CSS Ihren Loader mit Pseudoelementen (oder fügen Sie Klasse oder ID zu einem anderen Element hinzu, nicht zu einem Körper, wie Sie möchten) - Sie können die Hintergrundfarbe auf undurchsichtig oder transparent usw. einstellen. Beispiel:

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

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

Bearbeiten Sie den Speicherort Ihrer index.html-Datei im öffentlichen Ordner. Kopieren Sie Ihr Bild an denselben Speicherort wie index.html im öffentlichen Ordner. Ersetzen Sie dann den Teil des Inhalts von index.html, der <div id="root"> </div>Tags enthält, durch den unten angegebenen HTML-Code.

<div id="root">  <img src="logo-dark300w.png" alt="Spideren" style="vertical-align: middle; position: absolute;
   top: 50%;
   left: 50%;
   margin-top: -100px; /* Half the height */
   margin-left: -250px; /* Half the width */" />  </div>

Das Logo wird jetzt während des Ladevorgangs in der Mitte der Seite angezeigt. Und wird dann nach einigen Sekunden durch Reagieren ersetzt.

Magnus Melwin
quelle
2

Sie brauchen nicht so viel Aufwand, hier ist ein einfaches Beispiel.

<!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>

Sie können damit herumspielen HTMLund CSSdafür sorgen, dass es wie Ihr Beispiel aussieht.

Ahmed Kamal
quelle
1

Die wichtigste Frage ist: Was meinst du mit "Laden"? Wenn Sie über das physische Element sprechen, das gemountet wird, sind einige der ersten Antworten hier großartig. Wenn Ihre App jedoch als erstes die Authentifizierung überprüft, laden Sie tatsächlich Daten aus dem Backend, ob der Benutzer ein Cookie übergeben hat, das ihn als autorisierten oder nicht autorisierten Benutzer kennzeichnet.

Dies basiert auf Redux, aber Sie können es leicht in ein einfaches Reaktionszustandsmodell ändern.

Aktionsersteller:

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
      });
    }
  };
};

Der letzte Teil bedeutet, ob der Benutzer autorisiert ist oder nicht, der Ladebildschirm verschwindet, nachdem eine Antwort empfangen wurde.

So könnte eine geladene Komponente aussehen:

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();
 }

}

Wenn state.loading wahr ist, wird immer ein Ladebildschirm angezeigt. Auf componentDidMount rufen wir unsere Funktion getTodos auf, bei der es sich um einen Aktionsersteller handelt, der state.loading fälschlicherweise aktiviert, wenn eine Antwort angezeigt wird (was ein Fehler sein kann). Unsere Komponenten werden aktualisiert, Aufrufe werden erneut gerendert, und dieses Mal wird aufgrund der if-Anweisung kein Ladebildschirm angezeigt.

user3605834
quelle
1

Der Start der React-App basiert auf dem Download des Hauptpakets. Die React-App wird erst gestartet, nachdem das Hauptpaket im Browser heruntergeladen wurde. Dies gilt sogar für die Lazy-Loading-Architektur. Tatsache ist jedoch, dass wir den Namen von Bundles nicht genau angeben können. Weil das Webpack am Ende jedes Bundles einen Hashwert hinzufügt, wenn Sie den Befehl 'npm run build' ausführen. Natürlich können wir dies vermeiden, indem wir die Hash-Einstellungen ändern, aber das Cache-Datenproblem im Browser wird ernsthaft beeinträchtigt. Browser können die neue Version aufgrund desselben Bundle-Namens möglicherweise nicht verwenden. . Wir brauchen einen Webpack + js + CSS-Ansatz, um diese Situation zu bewältigen.

Ändern Sie die Datei public / index.html wie folgt

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

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=3.0, shrink-to-fit=no">
  <meta name="theme-color" content="#000000">
  <!--
      manifest.json provides metadata used when your web app is added to the
      homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
    -->
  <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
  <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
  <style>
 .percentage {
      position: absolute;
      top: 50%;
      left: 50%;
      width: 150px;
      height: 150px;
      border: 1px solid #ccc;
      background-color: #f3f3f3;
      -webkit-transform: translate(-50%, -50%);
          -ms-transform: translate(-50%, -50%);
              transform: translate(-50%, -50%);
      border: 1.1em solid rgba(0, 0, 0, 0.2);
      border-radius: 50%;
      overflow: hidden;
      display: -webkit-box;
      display: -ms-flexbox;
      display: flex;
      -webkit-box-pack: center;
          -ms-flex-pack: center;
              justify-content: center;
      -webkit-box-align: center;
          -ms-flex-align: center;
              align-items: center;
    }

    .innerpercentage {
      font-size: 20px;
    }
  </style>
  <script>
    function showPercentage(value) {
      document.getElementById('percentage').innerHTML = (value * 100).toFixed() + "%";
    }
    var req = new XMLHttpRequest();
    req.addEventListener("progress", function (event) {
      if (event.lengthComputable) {
        var percentComplete = event.loaded / event.total;
        showPercentage(percentComplete)
        // ...
      } else {
        document.getElementById('percentage').innerHTML = "Loading..";
      }
    }, false);

    // load responseText into a new script element
    req.addEventListener("load", function (event) {
      var e = event.target;
      var s = document.createElement("script");
      s.innerHTML = e.responseText;
      document.documentElement.appendChild(s);
      document.getElementById('parentDiv').style.display = 'none';

    }, false);

    var bundleName = "<%= htmlWebpackPlugin.files.chunks.main.entry %>";
    req.open("GET", bundleName);
    req.send();

  </script>
  <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->

  <title>App Name</title>
  <link href="<%= htmlWebpackPlugin.files.chunks.main.css[0] %>" rel="stylesheet">
</head>

<body>
  <noscript>
    You need to enable JavaScript to run this app.
  </noscript>
  <div id="parentDiv" class="percentage">
    <div id="percentage" class="innerpercentage">loading</div>
  </div>
  <div id="root"></div>
  <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
</body>

</html>

Ändern Sie in Ihrer Produktions-Webpack-Konfiguration die Option HtmlWebpackPlugin wie folgt

 new HtmlWebpackPlugin({
          inject: false,
...

Möglicherweise müssen Sie den Befehl 'eject' verwenden, um die Konfigurationsdatei abzurufen. Das neueste Webpack hat möglicherweise die Option, das HtmlWebpackPlugin zu konfigurieren, ohne das Projekt auszuwerfen. Geben Sie hier die Bildbeschreibung ein

Anoop Chillayi Kochappu
quelle
1

Ich habe auch die Antwort von @Ori Drori verwendet und es geschafft, sie zum Laufen zu bringen. Wenn Ihr React-Code wächst, werden auch die Bundles kompiliert, die der Client-Browser beim ersten Zugriff herunterladen muss. Dies führt zu einem Problem mit der Benutzererfahrung, wenn Sie nicht gut damit umgehen.

Was ich zu der Antwort von @Ori hinzugefügt habe, war das Hinzufügen und Ausführen der Onload-Funktion im Attribut index.html on onload des Body-Tags, sodass der Loader verschwindet, nachdem alles beim Durchsuchen vollständig geladen wurde. Siehe den folgenden Ausschnitt:

<html>
  <head>
     <style>
       .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);
          }
        }
     </style>
     <script>
       function onLoad() {
         var loader = document.getElementById("cpay_loader");loader.className = "";}
     </script>
   </head>
   <body onload="onLoad();">
     more html here.....
   </body>
</html>
Joseph Tabajjwa
quelle
1

Was ist mit Pace?

Verwenden Sie diese Linkadresse hier.

https://github.hubspot.com/pace/docs/welcome/

1.Wählen Sie auf ihrer Website den gewünschten Stil aus und fügen Sie ihn in index.css ein

2.go to cdnjs Kopieren Sie den Link für Pace Js und fügen Sie ihn zu Ihren Skript-Tags in public / index.html hinzu

3. Es erkennt automatisch Weblasten und zeigt das Tempo oben im Browser an.

Sie können auch die Höhe und Animation im CSS ändern.

roqkabel
quelle
Genial und kann in kürzester Zeit integriert werden.
UzumakiL