我正在尝试创建计时器组件。最初应该只有开始按钮作为第一个列表项。单击按钮时,开始按钮应该消失,停止按钮应该显示在同一个 li 元素中。停止按钮旁边应该有计时器。单击停止按钮时,完成按钮应与同一 li 元素中的计数器一起显示,停止按钮应消失。同时单击停止按钮时新建,应创建新的 li 项目。新的 li 项目应该有再次启动按钮,这应该在循环中。
我真的很困惑如何用角度创建这个组件。这是我的代码:
<div class="bg-white p-10 rounded-lg shadow-md">
<h1 class="text-xl text-center pb-4">Twikit Time-it</h1>
<div class="time-tracker">
<ng-container *ngIf="!isTimerRunning; else timerRunning">
<div class="flex justify-between align-center pb-2">
<app-button
type="start"
(click)="startTimer()"
name="start"
></app-button>
<div>Timer hasn't started yet!</div>
</div>
</ng-container>
<ng-template #timerRunning>
<div class="flex justify-between align-center pb-2">
<app-button
type="stop"
(click)="stopTimer()"
name="stop"
*ngIf="isStopButtonShown"
></app-button>
<app-button
type="done"
(click)="addRecord(); isDoneButtonShown = false; isStopButtonShown = false; isStartButtonShown = true;"
name="done"
*ngIf="isDoneButtonShown"
></app-button>
<ng-container *ngIf="isStartButtonShown">
<app-button
type="start"
(click)="addRecord()"
name="add"
></app-button>
</ng-container>
<div *ngIf="isTimerRunning; else noTimer"> {{ formatElapsedTime(count) }}</div>
<ng-template #noTimer>
<div>0 secs</div>
</ng-template>
</div>
</ng-template>
<ul>
<li *ngFor="let record of records" class="flex justify-between align-center pb-2">
<ng-container *ngIf="record.isDone; else notDone">
<app-button
type="done"
name="done"
></app-button>
<div>{{ formatElapsedTime(record.duration) }}</div>
</ng-container>
<ng-template #notDone>
<ng-container *ngIf="isTimerRunning">
<app-button
type="stop"
(click)="stopTimer()"
name="stop"
></app-button>
<div>{{ formatElapsedTime(count) }}</div>
</ng-container>
<ng-container *ngIf="!isTimerRunning">
<app-button
type="start"
(click)="resumeTimer(record)"
name="start"
></app-button>
<div>0 secs</div>
</ng-container>
</ng-template>
</li>
</ul>
<button *ngIf="records.length > 1" (click)="toggleSort()">Sort</button>
</div>
</div>
这是我的打字文件:
import { Component } from '@angular/core';
interface Record {
startTime: Date;
endTime: Date;
duration: number;
isDone: boolean;
}
@Component({
selector: 'app-tracker',
templateUrl: './tracker.component.html',
styleUrls: ['./tracker.component.css'],
})
export class TrackerComponent {
records: Record[] = [];
isTimerRunning = false;
private startTime: Date | null = null;
private timerId: any;
private sortAscending = true;
public count = 0;
public isStartButtonShown = true;
public isStopButtonShown = false;
public isDoneButtonShown = false;
startTimer(): void {
this.isStartButtonShown = false;
this.isStopButtonShown = true;
this.startTime = new Date();
this.timerId = setInterval(() => {
this.count += 1000;
this.isTimerRunning = true;
}, 1000);
}
stopTimer(): void {
this.isStopButtonShown = false;
this.isDoneButtonShown = true;
const endTime = new Date();
const duration = endTime.getTime() - this.startTime!.getTime();
clearInterval(this.timerId);
this.isTimerRunning = false;
this.records.unshift({
startTime: this.startTime!,
endTime: endTime,
duration: duration,
isDone: true,
});
this.startTime = null;
this.count = 0;
this.isStartButtonShown = true;
this.isDoneButtonShown = false;
// Add a new record with a start button
this.addRecord();
}
resumeTimer(record: Record): void {
this.isTimerRunning = true;
this.startTime = new Date();
this.timerId = setInterval(() => {
record.duration = new Date().getTime() - this.startTime!.getTime();
}, 1000);
}
addRecord(): void {
this.records.push({
startTime: null!,
endTime: null!,
duration: 0,
isDone: false,
});
}
toggleSort(): void {
this.sortAscending = !this.sortAscending;
if (this.sortAscending) {
this.records.sort((a, b) => a.startTime.getTime() - b.startTime.getTime());
} else {
this.records.sort((a, b) => b.startTime.getTime() - a.startTime.getTime());
}
}
formatElapsedTime(milliseconds: number): string {
const totalSeconds = Math.floor(milliseconds / 1000);
const minutes = Math.floor(totalSeconds / 60);
const seconds = totalSeconds % 60;
const paddedMinutes = String(minutes).padStart(2, '0');
const paddedSeconds = String(seconds).padStart(2, '0');
return `${paddedMinutes}:${paddedSeconds}`;
}
}
几个小时以来,我一直在尝试创建这样的组件但尚未成功,Mockup 或多或少应该是这样的:
我在初始阶段尝试显示,只有开始按钮。