【问题标题】:display a pre-loader in Angular before it load first component在加载第一个组件之前在 Angular 中显示预加载器
【发布时间】:2019-03-19 05:37:45
【问题描述】:

我正在使用 Angular 6。

我的应用程序在加载组件之前需要几秒钟的时间,而这段时间用于加载资源和验证用户。

当这一切发生时,我的应用程序显示一个空白页。

我想用 preloader 替换那个丑陋的白色页面,该页面将在所有后台进程完成之前一直显示。

为此,我在 index.html 之内添加了一个 CSS 加载微调器

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>My App</title>
  <base href="/">

  <!-- Fonts and icons -->

</head>
<body>
  <app-root>
    <!-- Pre-loading spinner -->
    <!-- This code within the app-root will be wiped of once the child component is loaded -->
    <!-- This code will not even be shown in the source code once the child component is loaded -->
    <!-- We can put any code css/html/image/etc here -->

    <style>
      /** CSS here. Since it will be wiped totally, 'll not cause any impact to the core stylesheet.
    </style>

    Loading<span class="d">.</span><span class="d d-2">.</span><span class="d d-3">.</span>
  </app-root>
</body>
</html>

这会显示一个类似的页面

但问题是这样的。第一个加载的组件是 app.component.html,它有以下内容

<router-outlet></router-outlet>

这进一步加载了另一个组件 admin-layout-component.html 的内容

<div class="wrapper">
  <div class="sidebar" data-color="red">
    <app-sidebar></app-sidebar>
  </div>
  <div class="main-panel">
    <app-navbar></app-navbar>
    <router-outlet></router-outlet>
    <app-footer></app-footer>
  </div>
</div>

一旦 app.component 被加载,来自 index.html 的微调器内容就会被移除并开始显示空白页面,直到 admin-layout 已加载。

我尝试在 app.component.html 的 router-outlet 中添加相同的样式代码,但是当组件加载时,内容与微调器一起添加并且微调器不会从其他页面中删除。

在加载仪表板页面之前,如何在 app.component.html 上显示微调器。

这是一个如何工作的视频:https://youtu.be/RSlTi0EQHm4

【问题讨论】:

    标签: angular angular6


    【解决方案1】:

    首先,您的实现是显示加载微调器的非常标准的方式。

    问题

    问题不在于应用程序组件。加载应用程序组件后微调器消失。您看到的空白页面是因为仪表板组件的大小很大,并且可能有多个 API 调用。所以基本上微调器按预期工作。问题在于仪表板组件

    修复

    1.如果要修复,则需要在仪表板组件中隐藏句柄微调器。 创建 a 并将您的微调器内容放入其中,而不是 &lt;app-root&gt;

    <body>
      <div id="loader">
         <!-- Pre-loading spinner -->
        <!-- This code within the app-root will be wiped of once the child component is loaded -->
        <!-- This code will not even be shown in the source code once the child component is loaded -->
        <!-- We can put any code css/html/image/etc here -->
    
        <style>
          /** CSS here. Since it will be wiped totally, 'll not cause any impact to the core stylesheet.
        </style>
    
        Loading<span class="d">.</span><span class="d d-2">.</span><span class="d d-3">.</span>
      </div>
    
      <app-root></app-root>
    </body>
    

    仪表板组件

    在ngAfterViewInit中隐藏id为loader的div

    @Component({selector: 'dashbaord', template: `...`})
    class DashboardComponent implements AfterViewInit {
      constructor(private elRef:ElementRef) {}
    
       ngAfterViewInit() {
         let loader = this.elRef.nativeElement.querySelector('#loader'); 
         loader.style.display = "none"; //hide loader
      }
    }
    

    【讨论】:

    • 这样我需要在所有组件中添加ngAfterViewInit。因为当直接从 URL 访问另一个组件时,例如 www.example.com/contacts,那么它也会像 dashboard 一样出现空白屏幕?
    • 此外,由于内联 CSS 影响了主应用程序的 CSS,因此它没有按预期工作。加载主要组件后,我想删除 CSS 和所有微调器内容。
    • 不是隐藏div,而是删除div this.elRef.nativeElement.innerHTML = "";的内容
    • 这将解决我的第二个查询,但第一个呢?我需要在所有组件中添加ngAfterViewInit 吗?这样当直接访问任何组件时,它都会按预期工作?
    • 第一个问题不会发生。一旦出现下一个组件或页面,第一个组件就会消失。如果您仍然有一些问题,那么您应该像大多数网站一样实施微调器。
    【解决方案2】:

    根据 Sunil 的回答,我在 Angular 8 中得到了这个工作。我从 App 组件中隐藏了 loader 元素,该组件在任何其他组件之前初始化。所以不需要到处添加这个。

    不推荐使用ElementRef 操作DOM,所以我改用Renderer2。

    index.html:

    <body class="theme-primary">
      <div id="loader">
        <style>
          .application-loading-container {
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            height: 100vh;
          }
    
          .application-loading-box {
            width: 300px;
            margin: 5px;
            text-align: center;
          }
        </style>
        <div class="application-loading-container">
          <div class="application-loading-box"><h2>Loading...</h2></div>
        </div>
      </div>
      <app-root></app-root>
    </body>
    

    app.component.ts:

    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.scss']
    })
    
    export class AppComponent implements AfterViewInit {
      constructor(private renderer: Renderer2) {}
    
      ngAfterViewInit() {
        let loader = this.renderer.selectRootElement('#loader');
        this.renderer.setStyle(loader, 'display', 'none');
      }
    }
    

    【讨论】:

    • 关于您关于使用 Renderer 而不是直接操作 DOM 的声明,您可能应该将:loader.style.display = "none"; 更改为 this.renderer.setStyle(loader, 'display', 'none');
    • 声明是关于使用 ElementRef 来操作 DOM。但是您的建议可能是首选的方法。我会更新我的帖子。
    • 您的回答对我很有帮助,现在一切正常,谢谢!
    【解决方案3】:

    组件

    @Component({
      selector: 'body[osk-root]',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.scss']
    })
    
    export class AppComponent{/* Not need remove element or change style*/}
    

    index.html

    <body osk-root><!--YOUR LOADER--></body>
    

    appcomponent成功加载后,angular清除body[osk-root]元素的innerHtml

    (注意我在 Angular 9 中像这样使用)

    【讨论】:

    • 这个非常完美,因为它不依赖于加载和立即显示的角度,我已经在 中包含了样式,所以它在开始时重置样式,就像魅力一样!要在这里测试,请从这里复制 HTML 并将其放在 index.html 中的 中,您应该有一个功能齐全的预加载屏幕 codepen.io/Cruelplatypus67/pen/rNLVggQ
    • 伙计,太完美了,非常感谢!
    猜你喜欢
    • 2019-10-28
    • 1970-01-01
    • 2020-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多