You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 5点击按钮时Spinner加载效果无效问题求助

解决Angular 5中点击按钮Spinner不显示的问题

我看了你的代码,问题主要出在loading状态的管理和异步操作的处理上,下面一步步帮你修复:

问题分析

  1. 组件的loading是私有变量:你在LoginComponent里声明了private loading: boolean;,Angular模板无法访问私有属性,所以*ngIf="loading"永远不会生效。
  2. 异步操作的时序错误:你在调用this.userSrv.login()后立刻把this.loading = false,但API请求是异步的,这会导致loading刚设为true就马上变回false,Spinner根本来不及显示。
  3. 组件和Service的loading状态不关联:Service里自己维护了一个loading变量,但组件模板用的是组件自己的,两者没有联动,所以Service里的loading变化不会反映到按钮上。

修复步骤

1. 修正组件的loading变量权限与登录逻辑

把组件里的loading改成public,同时修复判断语法、调整异步操作的loading控制:

export class LoginComponent implements OnInit {
  // 改成public,让模板可以直接访问
  public loading: boolean = false; 

  // ...其他代码

  login() {
    // 修复判断语法:用&&同时校验邮箱和密码
    if (this.user.email && this.user.password) { 
      this.loading = true;
      // 订阅Service返回的Observable,在回调中更新loading
      this.userSrv.login(this.user.email, this.user.password)
        .subscribe(
          (data) => {
            this.loading = false;
            if (data.token) {
              window.location.href = '/';
            } else {
              this.router.navigateByUrl('/login');
            }
          },
          (error) => {
            this.loading = false;
            this.router.navigateByUrl('/login');
          }
        );
    }
  }
}

2. 修改Service的login方法,返回Observable

不要在Service里直接subscribe,而是把Observable返回给组件,让组件统一控制loading状态:

@Injectable()
export class UserService {
  private loginUrl = this.globals.LOGIN_URL;
  private loggedIn = false;

  constructor(private http: Http, private router: Router, private globals: Globals) { }

  login(email: string, password: string): Observable<any> {
    let headers = new Headers();
    headers.append('Content-Type', 'application/json');
    
    return this.http.post(
      this.loginUrl, 
      JSON.stringify({ email, password }), 
      { headers }
    ).map(res => res.json()); // 提前处理返回的JSON数据,传给组件
  }
}

3. 模板代码保持不变(已正确)

你的模板逻辑没问题,只要组件的loading能被正常访问,就能显示Spinner:

<button type="submit" class="btn btn-accent btn-block btn-flat b-r-10" style="background: #FF473A;">
  Sign In <i class="fa fa-spinner fa-spin" *ngIf="loading"></i>
</button>

额外优化建议

可以用RxJS的finalize操作符统一处理loading重置,避免在成功/失败回调中重复写代码:

// 先导入操作符
import 'rxjs/add/operator/finalize';

// 组件的login函数中
this.userSrv.login(this.user.email, this.user.password)
  .finalize(() => this.loading = false) // 请求完成(无论成功/失败)都会执行
  .subscribe(
    (data) => {
      data.token ? window.location.href = '/' : this.router.navigateByUrl('/login');
    },
    () => {
      this.router.navigateByUrl('/login');
    }
  );

这样修改后,点击按钮时loading会设为true,Spinner持续显示直到API请求完成,就能实现你想要的加载效果了。

内容的提问来源于stack exchange,提问作者CE0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:28:47