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

多行列计时器切换问题:启动新计时时旧计时无法正常暂停

嗨,我帮你搞定这个计时器问题啦!

看了你的代码后,发现问题出在你的taskService里——你现在只用了单个interval、time变量来管理所有行的计时器,这就导致每次启动新行时,会直接覆盖掉之前的计时器实例;暂停的时候也是清除这个唯一的interval,自然所有行的计时器都跟着停了。

要解决这个问题,我们得给每一行单独存一份计时器的状态、时间和interval实例,不能大家共用一组变量。下面是具体的修改方案:


第一步:重构你的 TaskService

把服务里的全局变量改成一个对象,用行的id作为键,来存储每一行的计时器数据:

// task.service.ts
import { Injectable } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class TaskService {
  // 用对象存储每个行的计时器信息:key是行id,value包含interval、time、状态
  private timerMap: {
    [key: string]: { interval: number | null; time: number; state: 'start' | 'pause' }
  } = {};

  startTimer(data: { key: { id: string }; rowIndex: number }) {
    const rowId = data.key.id;
    // 如果该行之前有计时器,先清掉旧的,避免重复启动
    if (this.timerMap[rowId]) {
      clearInterval(this.timerMap[rowId].interval);
    }
    // 初始化当前行的计时器数据
    this.timerMap[rowId] = {
      interval: null,
      time: 0,
      state: 'start'
    };

    // 启动当前行的计时器
    this.timerMap[rowId].interval = window.setInterval(() => {
      this.timerMap[rowId].time++;
      // 如果需要在模板显示时间,后续可以通过get方法获取这个值
    }, 1000);
  }

  pauseTimer(data: { key: { id: string }; rowIndex: number }) {
    const rowId = data.key.id;
    if (this.timerMap[rowId]) {
      clearInterval(this.timerMap[rowId].interval);
      this.timerMap[rowId].state = 'pause';
      this.timerMap[rowId].interval = null;
    }
  }

  // 获取指定行的累计时间
  getRowTime(rowId: string): number {
    return this.timerMap[rowId]?.time || 0;
  }

  // 获取指定行的状态(启动/暂停)
  getRowState(rowId: string): 'start' | 'pause' | undefined {
    return this.timerMap[rowId]?.state;
  }
}

第二步:调整组件里的 startTimer 方法

现在启动新行时,我们可以精准暂停其他正在运行的行,而不是误杀所有计时器:

// 你的组件.ts文件
startTimer(data) {
  // 遍历所有行,把除了当前点击行之外的活跃计时器暂停
  this.data.forEach(row => {
    const rowState = this.taskService.getRowState(row.id);
    if (rowState === 'start' && row.id !== data.key.id) {
      this.taskService.pauseTimer({ key: { id: row.id }, rowIndex: row.rowIndex });
    }
  });

  // 启动当前点击行的计时器
  this.taskService.startTimer(data);
}

pauseTimer(data) {
  this.taskService.pauseTimer(data);
}

为什么这样改就好使了?

  • 每个行独立拥有计时器:timerMap对象给每一行都存了专属的interval、时间和状态,再也不会出现新行启动覆盖旧行计时器的问题。
  • 精准控制单个行:启动新行时,只会暂停其他正在运行的行,不会影响已经暂停的行,也不会误清所有计时器。
  • 保留累计时间:之前的代码一暂停就把time重置为0,现在修改后,暂停的行再次启动可以继续累计时间(如果需要重置的话,直接在startTimer里把time设为0就行,按需调整)。

如果你的模板需要显示每一行的时间和状态,现在可以通过taskService.getRowTime(row.id)和taskService.getRowState(row.id)来获取对应行的数据啦!


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 12:32:29