React - Hiển thị màn hình tải trong khi DOM đang hiển thị?


148

Đây là một ví dụ từ trang ứng dụng Google Adsense. Màn hình tải hiển thị trước trang chính hiển thị sau.

nhập mô tả hình ảnh ở đây

Tôi không biết cách thực hiện tương tự với React vì nếu tôi thực hiện tải màn hình được hiển thị bởi thành phần React, nó sẽ không hiển thị trong khi trang đang tải vì phải chờ DOM kết xuất trước đó.

Cập nhật :

Tôi đã làm một ví dụ về cách tiếp cận của mình bằng cách đưa trình tải màn hình vào index.htmlvà loại bỏ nó trong componentDidMount()phương pháp Vòng đời React .

Ví dụphản ứng tải màn hình .


Hiển thị những gì bạn muốn hiển thị trong js đơn giản, sau đó làm cho nó bị ẩn hoặc xóa khỏi DOM khi phản ứng đã được gắn kết. Tất cả bạn cần làm là để ẩn nó khỏi mã phản ứng.
FurkanO

Điều này chỉ đơn giản là tuyệt vời! Cảm ơn bạn.
Arman Karimi

Câu trả lời:


100

Điều này có thể được thực hiện bằng cách đặt biểu tượng tải trong tệp html của bạn (index.html cho ex), để người dùng thấy biểu tượng ngay sau khi tệp html đã được tải.

Khi ứng dụng của bạn tải xong, bạn chỉ cần xóa biểu tượng tải đó trong móc vòng đời, tôi thường làm điều đó trong componentDidMount.


11
Nếu bạn gắn thành phần gốc vào nút cha của biểu tượng đó, thậm chí không cần phải gỡ bỏ thủ công. React sẽ dọn sạch các nút con gắn kết và đặt DOM mới được kết xuất của nó ở đó.
rishat

6
Tôi không đặt biểu tượng bên trong nút gốc của ứng dụng React, nó chỉ cảm thấy không phù hợp với tôi
kkkkkkk

170

Mục đích

Khi trang html được hiển thị, hiển thị một công cụ quay vòng ngay lập tức (trong khi React tải) và ẩn nó sau khi React sẵn sàng.

Vì spinner được hiển thị bằng HTML / CSS thuần (bên ngoài miền React), React không nên trực tiếp kiểm soát quá trình hiển thị / ẩn và việc triển khai phải trong suốt đối với React.

Giải pháp 1 - lớp: giả giả

Vì bạn kết xuất phản ứng vào một thùng chứa DOM - <div id="app"></div>, bạn có thể thêm một công cụ quay vòng vào bộ chứa đó và khi phản ứng sẽ tải và kết xuất, công cụ quay vòng sẽ biến mất.

Bạn không thể thêm một phần tử DOM (ví dụ div) bên trong gốc phản ứng, vì React sẽ thay thế nội dung của vùng chứa ngay khi ReactDOM.render()được gọi. Ngay cả khi bạn kết xuất null, nội dung vẫn sẽ được thay thế bằng một nhận xét - <!-- react-empty: 1 -->. Điều này có nghĩa là nếu bạn muốn hiển thị trình tải trong khi các thành phần chính gắn kết, dữ liệu đang tải, nhưng không có gì thực sự được hiển thị, một đánh dấu trình tải được đặt bên trong container (<div id="app"><div class="loader"></div></div> ví dụ) sẽ không hoạt động.

Một cách giải quyết là thêm lớp spinner vào thùng chứa phản ứng và sử dụng :emptylớp giả . Công cụ quay vòng sẽ hiển thị, miễn là không có gì được hiển thị trong vùng chứa (ý kiến ​​không được tính). Ngay khi phản ứng ám chỉ thứ gì đó ngoài bình luận, bộ nạp sẽ biến mất.

ví dụ 1

Trong ví dụ này, bạn có thể thấy một thành phần hiển thị nullcho đến khi nó sẵn sàng. Container cũng là trình nạp - <div id="app" class="app"></div>và lớp của trình tải sẽ chỉ hoạt động nếu nó :empty(xem các bình luận trong mã):

Ví dụ 2

Một biến thể của việc sử dụng :emptylớp giả để hiển thị / ẩn bộ chọn, đang đặt spinner làm thành phần anh chị em với vùng chứa ứng dụng và hiển thị nó miễn là vùng chứa trống bằng cách sử dụng bộ kết hợp anh chị em liền kề ( +):


Giải pháp 2 - Truyền spinner "xử lý" làm đạo cụ

Để có một kiểm soát tốt hạt hơn so với trạng thái spinners hiển thị, tạo ra hai chức năng showSpinnerhideSpinner, và vượt qua chúng để container gốc qua đạo cụ. Các chức năng có thể thao tác DOM hoặc làm bất cứ điều gì cần thiết để kiểm soát spinner. Theo cách này, React không nhận thức được "thế giới bên ngoài", cũng không cần phải kiểm soát DOM trực tiếp. Bạn có thể dễ dàng thay thế các chức năng để kiểm tra hoặc nếu bạn cần thay đổi logic và bạn có thể chuyển chúng cho các thành phần khác trong cây React.

ví dụ 1

Ví dụ 2 - móc

Ví dụ này sử dụng useEffecthook để ẩn spinner sau khi mount thành phần.


Bạn có thể làm rõ 2 phần mã cuối cùng nên ở đâu? Đầu tiên rõ ràng là trong tệp src javascript cho thành phần phản ứng, thứ ba tôi đoán sẽ đi vào mẫu html được hiển thị bởi tệp js đã nói, nhưng thứ hai sẽ đi đâu?
levraininjaneer

1
Thứ 2 là CSS. Tôi đã sử dụng CSS toàn cầu, nhưng bạn có thể sử dụng Mô-đun CSS hoặc CSS trong JS. Thứ 3 là tệp HTML, có thể bao gồm đánh dấu spinner nếu cần (ví dụ thứ 2).
Ori Drori

Thời gian chờ đó không tốt khi hiệu suất được xem xét.
khô lá

4
@dryleaf - setTimeout không phải là một phần của giải pháp. Nó mô phỏng chờ đợi một hành động không đồng bộ trước khi hiển thị nội dung.
Ori Drori

Tôi sử dụng cách tiếp cận tương tự. Tôi không thể tìm thấy bất cứ điều gì trong gói web có thể giúp tôi phá vỡ bộ đệm cho tệp css cần thiết cho trình tải. Bạn có thể giúp?
hamza-jutt

40

Cách giải quyết cho việc này là:

Trong chức năng kết xuất của bạn làm một cái gì đó như thế này:

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

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

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

Khởi tạo isLoading là true trong hàm tạo và false trên thành phầnDidMount


Khi chúng ta đã gọi phương thức ajax để tải dữ liệu đến các thành phần con. thành phầnDidMount được gọi trước khi nhập dữ liệu thành phần con. Làm thế nào chúng ta khắc phục loại vấn đề này?
dush88c

2
Đối với Mounting Life cyle thì không sao, bạn có muốn thêm cái gì đó cho vòng đời cập nhật không?
zakir

Tôi có phải làm điều này trong tất cả các trang hay chỉ trong mục nhập ứng dụng
Pedro JR

16

Nếu bất cứ ai đang tìm kiếm một thư viện thả xuống, zero-config và zero-Depencies cho trường hợp sử dụng ở trên, hãy thử speed.js ( http://github.hubspot.com/pace/docs/welcome/ ).

Nó tự động móc vào các sự kiện (ajax, readyState, lịch sử đẩy, vòng lặp sự kiện js, v.v.) và hiển thị trình tải tùy chỉnh.

Hoạt động tốt với các dự án phản ứng / chuyển tiếp của chúng tôi (xử lý các thay đổi điều hướng bằng cách sử dụng bộ định tuyến phản ứng, yêu cầu chuyển tiếp) (Không liên quan; đã sử dụng speed.js cho các dự án của chúng tôi và nó hoạt động rất tốt)


Chào! Bạn có thể cho tôi biết làm thế nào để sử dụng nó với phản ứng?
uneet7

chỉ cần đính kèm kịch bản public/index.htmlvà chọn một phong cách. Đây là plugin đơn giản, tuyệt vời. cảm ơn bạn.
PJ3

Tôi sẽ không tìm thấy tốc độ mà không có câu trả lời này. Thật dễ dàng để bao gồm, và với một chút ma thuật CSS và một số tệp đính kèm sự kiện, tôi có thể chặn / vô hiệu hóa ứng dụng trong quá trình chuyển đổi và tùy chỉnh spinner.
đảo ngược.

12

Khi ứng dụng React của bạn rất lớn, thực sự cần có thời gian để nó khởi động và chạy sau khi trang được tải. Giả sử, bạn gắn phần React của mình vào ứng dụng #app. Thông thường, phần tử này trong index.html của bạn chỉ đơn giản là một div trống:

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

Thay vào đó, những gì bạn có thể làm là đặt một số kiểu dáng và một loạt các hình ảnh ở đó để làm cho nó trông đẹp hơn giữa tải trang và kết xuất ứng dụng React ban đầu sang 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>

Sau khi tải trang, người dùng sẽ thấy ngay nội dung gốc của index.html. Ngay sau đó, khi React sẵn sàng gắn toàn bộ hệ thống phân cấp của các thành phần được kết xuất vào nút DOM này, người dùng sẽ thấy ứng dụng thực tế.

Lưu ý class, không className. Đó là bởi vì bạn cần phải đặt nó vào tệp html của bạn.


Nếu bạn sử dụng SSR, mọi thứ sẽ ít phức tạp hơn vì người dùng thực sự sẽ thấy ứng dụng thực sự ngay sau khi tải trang.


Công việc này tôi cũng có hai nơi tải xảy ra. Một là ứng dụng lớn. và tiếp theo là chuẩn bị (lắp các bộ phận khác nhau.) Vì vậy, tôi có một bước nhấp nháy vì app.render tiếp quản và hình ảnh động được đặt lại ( thực sự được thay thế .) Có cách nào để tránh đèn flash đó không? React sẽ so sánh DOM một với một? Nhưng từ những gì tôi hiểu React đã thêm tất cả các loại dữ liệu riêng tư vào các thẻ ...
Alexis Wilke

12

Điều này sẽ xảy ra trước khi ReactDOM.render()mất quyền kiểm soát gốc <div> . Tức là ứng dụng của bạn sẽ không được gắn kết cho đến thời điểm đó.

Vì vậy, bạn có thể thêm trình tải của bạn index.htmltrong tệp của bạn bên trong thư mục gốc <div>. Và điều đó sẽ hiển thị trên màn hình cho đến khi React tiếp quản.

Bạn có thể sử dụng bất cứ yếu tố nào của trình tải hoạt động tốt nhất cho bạn ( svgví dụ với hoạt hình).

Bạn không cần phải xóa nó trên bất kỳ phương pháp vòng đời nào. React sẽ thay thế bất kỳ đứa trẻ gốc nào <div> bằng kết xuất của bạn <App/>, như chúng ta có thể thấy trong GIF bên dưới.

Ví dụ về CodeSandbox

nhập mô tả hình ảnh ở đây

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

Sử dụng debuggerđể kiểm tra trang trước khi ReactDOM.render()chạy.

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

một giải pháp đẹp và thanh lịch
Gal Margalit

1
Tôi rất vui vì nó giúp!
cbdeveloper

9

Ngày nay chúng ta có thể sử dụng móc cũng như trong 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;

5

Đặt thời gian chờ trong thành phầnDidMount hoạt động nhưng trong ứng dụng của tôi, tôi nhận được cảnh báo rò rỉ bộ nhớ. Hãy thử một cái gì đó như thế này.

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

4

Tôi đã phải đối phó với vấn đề đó gần đây và đưa ra một giải pháp, nó hoạt động tốt với tôi. Tuy nhiên, tôi đã thử giải pháp @Ori Drori ở trên và thật không may là nó không hoạt động đúng (có một số độ trễ + Tôi không thích cách sử dụng setTimeoutchức năng ở đó).

Đây là những gì tôi nghĩ ra:

index.html tập tin

headThẻ bên trong - kiểu cho chỉ báo:

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

Bây giờbodythẻ:

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

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

Và sau đó xuất hiện một logic rất đơn giản, bên trong app.jstệp (trong chức năng kết xuất):

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

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

Làm thế nào nó hoạt động?

Khi thành phần đầu tiên (trong ứng dụng của tôi, nó app.jscũng hoạt động tốt trong hầu hết các trường hợp) gắn kết chính xác, spinnernó sẽ bị ẩn với việc áp dụng hiddenthuộc tính cho nó.

Điều quan trọng hơn để thêm - !spinner.hasAttribute('hidden')điều kiện ngăn không cho thêm hiddenthuộc tính vào công cụ quay vòng với mỗi lần gắn kết thành phần, vì vậy thực tế nó sẽ chỉ được thêm một lần, khi toàn bộ ứng dụng tải.


4

Tôi đang sử dụng gói Reac -Progress-2 npm, không phụ thuộc 0 và hoạt động rất tốt trong ReactJS.

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

Cài đặt:

npm install react-progress-2

Bao gồm Reac-Progress-2 / main.css cho dự án của bạn.

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

Bao gồm react-progress-2và đặt nó ở đâu đó trong thành phần hàng đầu, ví dụ:

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

Bây giờ, bất cứ khi nào bạn cần hiển thị một chỉ báo, chỉ cần gọi Progress.show(), ví dụ:

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

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

Xin lưu ý rằng các cuộc gọi showhidecác cuộc gọi được xếp chồng lên nhau, vì vậy sau các cuộc gọi hiển thị liên tiếp n, bạn cần thực hiện n cuộc gọi để ẩn một chỉ báo hoặc bạn có thể sử dụng Progress.hideAll().


4

Tôi cũng đang sử dụng React trong ứng dụng của mình. Đối với các yêu cầu tôi đang sử dụng công cụ chặn axios, vì vậy cách tuyệt vời để tạo màn hình trình tải (toàn trang như bạn đã đưa ra một ví dụ) là thêm lớp hoặc id vào ví dụ bên trong phần chặn (ở đây mã từ tài liệu chính thức với một số mã tùy chỉnh):

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

Và sau đó chỉ cần triển khai trong CSS trình tải của bạn với các phần tử giả (hoặc thêm lớp hoặc id vào phần tử khác, không phải phần thân như bạn muốn) - bạn có thể đặt màu nền thành mờ hoặc trong suốt, v.v ... Ví dụ:

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

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

3

Chỉnh sửa vị trí tệp index.html của bạn trong thư mục công cộng . Sao chép hình ảnh của bạn vào cùng vị trí với index.html trong thư mục công cộng. Và sau đó thay thế một phần nội dung của index.html chứa <div id="root"> </div>các thẻ thành mã html đã cho bên dưới.

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

Logo bây giờ sẽ xuất hiện ở giữa trang trong quá trình tải. Và sau đó sẽ được React thay thế sau vài giây.


2

Bạn không cần nhiều nỗ lực đó, đây là một ví dụ cơ bản.

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

Bạn có thể chơi xung quanh HTMLCSSđể làm cho nó giống như ví dụ của bạn.


1

Câu hỏi quan trọng nhất là: 'tải' nghĩa là gì? Nếu bạn đang nói về yếu tố vật lý được gắn kết, một số câu trả lời đầu tiên ở đây là tuyệt vời. Tuy nhiên, nếu điều đầu tiên mà ứng dụng của bạn thực hiện là kiểm tra xác thực, thì thứ bạn thực sự đang tải là dữ liệu từ phụ trợ cho dù người dùng đã chuyển một cookie gắn nhãn cho họ là người dùng được ủy quyền hay trái phép.

Điều này dựa trên redux, nhưng bạn có thể dễ dàng thay đổi nó thành mô hình trạng thái phản ứng đơn giản.

người tạo hành động:

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

Phần cuối cùng có nghĩa là người dùng có được xác thực hay không, màn hình tải sẽ biến mất sau khi nhận được phản hồi.

Đây là một thành phần tải nó có thể trông như thế nào:

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

}

Nếu state.loading là trung thực, chúng ta sẽ luôn thấy một màn hình tải. Trên thành phầnDidMount, chúng tôi gọi hàm getTodos của chúng tôi, đây là trình tạo hành động chuyển trạng thái. Tải sai khi chúng tôi nhận được phản hồi (có thể là lỗi). Thành phần của chúng tôi cập nhật, gọi lại kết xuất và lần này không có màn hình tải vì câu lệnh if.


1

Việc bắt đầu ứng dụng phản ứng dựa trên tải xuống gói chính. Ứng dụng React chỉ bắt đầu sau khi gói chính được tải xuống trong trình duyệt. Điều này thậm chí đúng trong trường hợp lười tải kiến ​​trúc. Nhưng thực tế là chúng ta không thể nói chính xác tên của bất kỳ gói nào. Bởi vì webpack sẽ thêm một giá trị băm vào cuối mỗi gói tại thời điểm bạn chạy lệnh 'npm run build'. Tất nhiên chúng ta có thể tránh điều đó bằng cách thay đổi cài đặt băm, nhưng nó sẽ ảnh hưởng nghiêm trọng đến vấn đề dữ liệu bộ đệm trong Trình duyệt. Các trình duyệt có thể không có phiên bản mới vì cùng tên gói. . chúng ta cần một cách tiếp cận webpack + js + CSS để xử lý tình huống này.

thay đổi công khai / index.html như dưới đây

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

Trong cấu hình webpack sản xuất của bạn, thay đổi tùy chọn HtmlWebpackPlugin thành bên dưới

 new HtmlWebpackPlugin({
          inject: false,
...

Bạn có thể cần sử dụng lệnh 'đẩy' để lấy tệp cấu hình. gói web mới nhất có thể có tùy chọn cấu hình HtmlWebpackPlugin mà không cần đẩy dự án. nhập mô tả hình ảnh ở đây


1

Tôi cũng đã sử dụng câu trả lời của @Ori Drori và quản lý để làm cho nó hoạt động. Khi mã React của bạn phát triển, các gói được biên dịch mà trình duyệt máy khách sẽ phải tải xuống khi truy cập lần đầu. Điều này đặt ra vấn đề về trải nghiệm người dùng nếu bạn không xử lý tốt.

Điều tôi đã thêm vào câu trả lời @Ori là thêm và thực thi chức năng onload trong thuộc tính index.html onload của thẻ body, để trình tải biến mất sau khi mọi thứ đã được tải đầy đủ trong trình duyệt, hãy xem đoạn trích bên dưới:

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

1

Còn việc sử dụng Pace thì sao?

Sử dụng địa chỉ liên kết này ở đây.

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

1.Trên trang web của họ, chọn kiểu bạn muốn và dán vào index.css

2.go to cdnjs Sao chép liên kết cho Pace Js và thêm vào thẻ script của bạn ở chế độ công khai / index.html

3. Nó tự động phát hiện tải web và hiển thị tốc độ tại trình duyệt Top.

Bạn cũng có thể sửa đổi chiều cao và hình ảnh động trong css.


Tuyệt vời và có thể được tích hợp trong thời gian không.
UzumakiL
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.