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

Angular 4跨组件修改变量:自定义加载倒计时时长问题

问题分析与解决方案

你遇到的核心问题是用错了组件通信方式:EventEmitter只适用于父子组件嵌套的场景(比如把<app-loading>直接写在home.component.html里作为子组件),但你是通过router.navigate跳转到独立的loading路由页面,这时候两个组件没有父子层级关系,EventEmitter根本无法传递数据。

下面给你两种最常用的解决方案,按优先级推荐:


方案一:通过路由参数传递倒计时时长(最直接)

这种方式不需要额外依赖,利用Angular路由的参数传递功能即可实现:

1. 修改home.component.ts的路由跳转逻辑

把倒计时时长作为路由参数传递:

import { Router } from '@angular/router';

// ...其他代码
applyChanges(){
  this.dashboard.applyChanges()
    .catch(err => {
      console.log("There was an error: "+err.status);
      console.log("There was an error: "+err.statusText);
      return Observable.throw(err);
    })
    .subscribe(data => {
      // 把时长作为路由参数传递
      this.router.navigate(['/loading', { duration: 34 }]);
    });
}

2. 修改loading.component.ts获取路由参数

首先导入ActivatedRoute,然后在组件中获取参数并初始化倒计时:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { AuthGuard } from '../guard/auth.guard';
import { Title } from '@angular/platform-browser';
import { ActivatedRoute } from '@angular/router'; // 新增导入

@Component({
  selector: 'app-loading',
  templateUrl: './loading.component.html',
  styleUrls: ['./loading.component.css']
})
export class LoadingComponent implements OnInit, OnDestroy { // 新增OnDestroy
  public timeLeft;
  public intervalId;

  constructor(
    public titleService: Title, 
    public guard: AuthGuard,
    private route: ActivatedRoute // 注入路由服务
  ) { }

  ngOnInit() {
    this.titleService.setTitle("Loading... | something");
    localStorage.removeItem('statusInfo');

    // 订阅路由参数,获取传递的时长
    this.route.paramMap.subscribe(params => {
      // 把参数转为数字,设置默认值10秒(可选)
      this.timeLeft = params.get('duration') ? +params.get('duration') : 10;
      this.startCounter(); // 拿到参数后再启动倒计时
    });
  }

  startCounter() {
    this.intervalId = setInterval(() => {
      if (this.timeLeft <= 1) { // 修正判断条件,防止负数
        clearInterval(this.intervalId); // 修正拼写错误:你原来写的interValId是大小写错误
        // 这里可以添加倒计时结束后的操作,比如跳转页面
        // this.router.navigate(['/home']);
      }
      this.timeLeft--;
    }, 1000);
  }

  // 组件销毁时清理定时器,防止内存泄漏
  ngOnDestroy() {
    if (this.intervalId) {
      clearInterval(this.intervalId);
    }
  }
}

3. 清理无效代码

删除loading.component.html中的无效事件绑定:

<!-- 删掉这个事件绑定:(loadingScreenStarted)="onScreenStart($event)" -->
<div class="container container-table">
  <!-- 原有内容保持不变 -->
</div>

方案二:通过共享服务传递数据(更灵活,适合复杂场景)

如果后续需要传递更多数据给loading组件,或者多个组件都要控制loading时长,推荐用共享服务:

1. 创建共享服务loading.service.ts

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class LoadingService {
  // BehaviorSubject会保存最新值,新订阅者能直接拿到当前值
  private durationSubject = new BehaviorSubject<number>(10);
  // 对外暴露可观察对象,防止外部直接修改Subject
  duration$ = this.durationSubject.asObservable();

  // 设置倒计时时长的方法
  setDuration(duration: number) {
    this.durationSubject.next(duration);
  }
}

2. 修改home.component.ts调用服务

import { LoadingService } from '../services/loading.service'; // 导入服务

// ...其他代码
constructor(
  private dashboard: DashboardService, // 你的原有服务
  private router: Router,
  private loadingService: LoadingService // 注入共享服务
) { }

applyChanges(){
  this.dashboard.applyChanges()
    .catch(err => {
      console.log("There was an error: "+err.status);
      console.log("There was an error: "+err.statusText);
      return Observable.throw(err);
    })
    .subscribe(data => {
      // 通过服务设置时长
      this.loadingService.setDuration(34);
      this.router.navigate(['/loading']);
    });
}

3. 修改loading.component.ts订阅服务

import { Component, OnInit, OnDestroy } from '@angular/core';
import { AuthGuard } from '../guard/auth.guard';
import { Title } from '@angular/platform-browser';
import { LoadingService } from '../services/loading.service'; // 导入服务
import { Subscription } from 'rxjs'; // 导入订阅对象,用于清理

@Component({
  selector: 'app-loading',
  templateUrl: './loading.component.html',
  styleUrls: ['./loading.component.css']
})
export class LoadingComponent implements OnInit, OnDestroy {
  public timeLeft;
  public intervalId;
  private durationSub: Subscription; // 保存订阅引用

  constructor(
    public titleService: Title, 
    public guard: AuthGuard,
    private loadingService: LoadingService // 注入服务
  ) { }

  ngOnInit() {
    this.titleService.setTitle("Loading... | something");
    localStorage.removeItem('statusInfo');

    // 订阅服务中的时长数据
    this.durationSub = this.loadingService.duration$.subscribe(duration => {
      this.timeLeft = duration;
      this.startCounter();
    });
  }

  startCounter() {
    this.intervalId = setInterval(() => {
      if (this.timeLeft <= 1) {
        clearInterval(this.intervalId);
        // 倒计时结束后的操作
      }
      this.timeLeft--;
    }, 1000);
  }

  ngOnDestroy() {
    // 清理定时器和订阅,防止内存泄漏
    if (this.intervalId) clearInterval(this.intervalId);
    if (this.durationSub) this.durationSub.unsubscribe();
  }
}

额外注意点

  1. 你原来的startCounter里有拼写错误:clearInterval(this.interValId);应该是clearInterval(this.intervalId);(驼峰大小写要一致)
  2. 建议在组件销毁时清理定时器和订阅,避免内存泄漏
  3. 如果用路由参数,记得在路由配置中允许可选参数(Angular默认支持,不需要额外配置)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:48:59