简体   繁体   English

Angular 4正确显示加载屏幕

[英]Angular 4 properly show loading screen

I'm using Angular 4 and I'd like to display a loading screen (basic spinner) between routes navigation. 我正在使用Angular 4,并且想在路线导航之间显示加载屏幕(基本微调器)。 I've used this technique in order to subscribe to the proper events, and used style.visibility in order to show/hide my spinner. 我使用这种技术来订阅适当的事件,并使用style.visibility来显示/隐藏我的微调器。

For some reason, although I'm correctly detecting the start and end events of the navigation, my spinner will not show. 由于某些原因,尽管我正确地检测了导航的开始和结束事件,但微调器不会显示。 In fact, although the visibility field is changing correctly, the spinner will still not show. 事实上,虽然知名度场正确改变,微调仍不会显示。

The only way I managed to display it is by forcing it to be set to 'visible' instead of 'hidden' at all times. 我设法显示它的唯一方法是通过始终将其设置为“可见”而不是“隐藏”。

Attached are relevant sections of my code: 附件是我的代码的相关部分:

app.component.ts: app.component.ts:

 constructor (private utils: UtilsService, private router: Router) { // Intercept all navigation events router.events.subscribe((event: RouterEvent) => { this.navigationInterceptor(event) }) // Calls our initializer utils.init(); } /* Intercept the navigator in order to display a loading screen */ navigationInterceptor(event: RouterEvent): void { // Starting the navigation if (event instanceof NavigationStart) { this.loading = true; } // The navigation ended if (event instanceof NavigationEnd) { this.loading = false; } // Set loading state to false in both of the below events to hide the spinner in case a request fails if (event instanceof NavigationCancel) { this.loading = false; } if (event instanceof NavigationError) { this.loading = false; } // Get our loading container var loading_container = document.getElementById('loader-container'); // If our loading container isn't available, this is the application first launch (ie. full refresh) // so we need to display a full loading logo if (loading_container) { // This is just a redirect, not a full refresh, so just hide or show the loading screen document.getElementById('loader-container').style.visibility = this.loading ? 'visible' : 'hidden'; } } 

app.component.html: app.component.html:

 <div style="position: fixed; left: 220px; width: calc(100% - 220px); height: 100%; z-index: 10000; background-color: rgba(255, 255, 255, 0.6);" id = "loader-container"> <div style = "top: 30%;" class="sk-spinner sk-spinner-double-bounce"> <div class="sk-double-bounce1"></div> <div class="sk-double-bounce2"></div> </div> </div> <!-- Main view/routes wrapper--> <router-outlet> </router-outlet> 

The problem is that you are trying to use native javascript in Angular in Constructor and by that time the DOM is not yet ready. 问题是您正在尝试在Constructor的Angular中使用本机javascript,而到那时DOM还没有准备好。 You should use it in AfterViewInit . 您应该在AfterViewInit使用它。

In this case you can have a loading variable and that all you need, use it in template to show and close spinner using ngIf depending upon the navigation. 在这种情况下,您可以有一个加载变量,您需要的所有变量都可以在模板中使用它,以根据导航显示并使用ngIf关闭微调ngIf

<div *ngIf = "loading" class = "main">
  <div class="spinner">
    <div class="rect1"></div>
    <div class="rect2"></div>
    <div class="rect3"></div>
    <div class="rect4"></div>
    <div class="rect5"></div>
  </div>

CSS 的CSS

.spinner > div {
  background-color: black;
  height: 100%;
  width: 6px;
  display: inline-block;

  -webkit-animation: sk-stretchdelay 1.2s infinite ease-in-out;
  animation: sk-stretchdelay 1.2s infinite ease-in-out;
}

.spinner .rect2 {
  -webkit-animation-delay: -1.1s;
  animation-delay: -1.1s;
}

.spinner .rect3 {
  -webkit-animation-delay: -1.0s;
  animation-delay: -1.0s;
}

.spinner .rect4 {
  -webkit-animation-delay: -0.9s;
  animation-delay: -0.9s;
}

.spinner .rect5 {
  -webkit-animation-delay: -0.8s;
  animation-delay: -0.8s;
}

@-webkit-keyframes sk-stretchdelay {
  0%, 40%, 100% { -webkit-transform: scaleY(0.4) }
  20% { -webkit-transform: scaleY(1.0) }
}

@keyframes sk-stretchdelay {
  0%, 40%, 100% {
    transform: scaleY(0.4);
    -webkit-transform: scaleY(0.4);
  }  20% {
       transform: scaleY(1.0);
       -webkit-transform: scaleY(1.0);
     }
}

Working example link and the git repo LINK 工作示例链接和git repo LINK

I've solved the problem. 我已经解决了问题。 The issue was that in JS DOM changes will execute only after the current code finished execution, thus delaying the appearance/disappearance of my spinner to the very end of the code execution. 问题在于,在JS DOM中,更改仅在当前代码完成执行后才执行,从而将我的微调器的出现/消失延迟到代码执行的最后。 This obviously resulted in it not showing at all, as the moment the code has finished executing it obviously already triggered the NavigationEnd event. 显然,这导致它根本没有显示,因为代码完成执行的那一刻显然已经触发了NavigationEnd事件。

I'm not sure if it's the correct solution, by I ended up using an onClick event on all of my navigation links: 我不确定这是否是正确的解决方案,因为我最终在所有导航链接上使用了onClick事件:

 <a (click)="routeClick('/Home')"><i class="fa fa-th-large"></i> <span class="nav-label">Home</span></a> 

And created the routeClick() function as follows: 并创建如下的routeClick()函数:

 public routeClick(href : string) : void { // Display the loading spinner UtilsService.loading = true; // Redirect to the new route asynchronously (IMPORTANT! Otherwise the spinner will not show!) setTimeout('location.href = "#' + href + '";', 1); } 

Which caused all DOM changes to be performed before the actual navigation began. 这导致所有DOM更改都在实际导航开始之前执行。

Hope this helps! 希望这可以帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM