为Angular 4的每个http请求显示加载动画gif

9

我是一个新手,对Angular不太熟悉,我需要在每次完成http请求时显示一个“spinner”。

我有许多组件:

<component-one></component-one>
<component-two></component-two>
<component-three></component-three>
<component-n></component-n>

每个组件都有一个HTTP请求来获取或保存一些数据,因此当HTTP请求发出时,我想显示我的<loading></loading> 组件,所以我认为在每个具有HTTP请求的组件中注入我的加载组件并不是一个好的做法。 我能否从angular添加过滤器或其他东西,使我可以自动加载<loading> 组件在每个具有HTTP请求的组件中?
另外,当HTTP请求完成后,我希望显示一个消息,例如“完成”或其他内容。
如果有人能为我提供解决方案,我会非常感激,谢谢。

2
可能是每个http请求上的Angular 2加载器的重复问题。 - eko
1
请查看此链接,其中包含有关该问题的问题和答案。 - Rahul Singh
5个回答

14

更新: plunker. 查看 app.ts. 抱歉所有内容都在一个文件中。

在Angular 4.3版本中,新增了支持拦截器的HttpClientModule。其主要思想是:

@Injectable()
export class LoadingIndicatorService {

    private _loading: boolean = false;

    get loading(): boolean {
        return this._loading;
    }

    onRequestStarted(): void {
        this._loading = true;
    }

    onRequestFinished(): void {
        this._loading = false;
    }
}

然后,您只需将Christopher的答案中的逻辑应用到您的HttpInterceptor上即可。

您唯一需要注意的是同时发送的请求。例如,这可以通过为每个请求生成唯一标识符并将其存储在某个地方直到请求完成来解决。

然后,您可以拥有一个全局的LoadingIndicator组件,该组件注入了LoadingIndicatorService

有关HttpClientModule的更多详细信息,请参见:https://medium.com/codingthesmartway-com-blog/angular-4-3-httpclient-accessing-rest-web-services-with-angular-2305b8fd654b


1
仅从4.3.0版本开始。这不是一个重大的发布版本。实际上,它应该是向后兼容的。 - Vadim Khamzin
1
@VadimKhamzin 感谢您提供的 Plunker 链接。不幸的是,当我在我的 app.component 中使用您的 "LoadingIndicatorService" 时,遇到了一个问题,因为它具有子组件。我总是收到一个 "ExpressionChangedAfterItHasBeenCheckedError" 错误。您有什么想法吗?据我所见,这似乎与 app.component 中的 "loading" 属性有关。 - Shamshiel
@Shamshiel,你能提供一下你的 Plunker 吗?我无法重现你的问题。 - Vadim Khamzin
@VadimKhamzin 我创建了一个简单的 Stackblitz 环境来展示问题:https://stackblitz.com/edit/angular-5b86se - Shamshiel
@VadimKhamzin 谢谢!不过你的 plunkr 示例有两个问题。1)第61行应该是 >= 而不是 !== 2)在将 this.loading(第97行)设置为防止 @Shamshiel 的问题后,应该运行 changeDetector.detectChanges()(也要导入 ChangeDetectorRef)。 - Devator
显示剩余2条评论

8

一个http请求会返回一个可以订阅的Observable对象。

例如,我们来看一下用户的认证。

在我的服务中:

login(email: string, password: string): Observable<User> {
    let url = this.authUrl + '/login';

    return this.http
        .post(url, JSON.stringify({ email, password }))
        .map(res => res.json());
}

我在组件中调用并订阅了这个方法:

 this.isLoading = true;
 this.authService.login(email, password)
        .subscribe(data => {
            this.isLoading = false;
            // Do whatever you want once the user is logged in
            // Where 'data' is the User returned by our http request
         }, error => {
            // Handle errors here
         }

注意布尔变量 isLoading 在尝试登录用户前被设置为true,在认证成功后被设置为false。
这意味着您可以使用此布尔变量显示和隐藏加载动画,例如:
<loading-component *ngIf="isLoading"></loading-component>

这正是我所寻找的。简单明了的标志。没有拦截器,没有其他东西。 - Vibhor Dube

6

3

使用 Angular 2+,创建一个可重用的工具组件。

import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'app-progress-mask',
  templateUrl: './progress-mask.component.html',
  styleUrls: ['./progress-mask.component.css']
})
export class ProgressMaskComponent implements OnInit {
  @Input() showProgress:boolean = false;
  constructor() { }

  ngOnInit() {
  }

}

HTML部分:

<div class="loadWrapper" *ngIf="showProgress">  
  <div class="loader"></div>  
</div>

CSS部分:

.loadWrapper {  
    background: rgba(0,0,0,0.3);  
    width: 100%;  
    height: 100%;  
    position: fixed;  
    top:0px;  
    left:0px;  
    z-index: 99999;  
}  
.loader {
    border: 5px solid #f3f3f3; /* Light grey */
    border-top: 5px solid #3d3e3f; /* gray */
    position: absolute;
    left: 50%;
    top: 50%;
    border-radius: 50%;
    width: 50px;
    height: 50px;
    animation: spin 2s linear infinite;
}

@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

现在将此代码插入到您的组件中

<app-progress-mask [showProgress]="showMask"></app-progress-mask>

将您组件的 showMask 属性绑定到可重用的 util 组件上


0

在你的component.ts文件中

public loading: boolean = false;

在你的组件.html文件中

<div *ngIf="!loading">
  <component-one></component-one>
  <component-two></component-two>
  <component-three></component-three>
  <component-n></component-n>
</div>

<loading *ngIf="loading"></loading>

每当您需要查看加载图标时,只需设置this.loading = true;,要隐藏它,则设置this.loading = false;。这将在加载时隐藏您不想看到的组件并显示加载图标。

请问您能否给我一个完整的例子或代码?我尝试了您的方法,但它对我不起作用。 - Hidayt Rahman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接