我有两个组件
todos.services.ts:
import { Injectable } from '@angular/core';
import { TodoItem } from '../interfaces/todo-item';
@Injectable({
providedIn: 'root',
})
export class TodosService {
protected todoList: TodoItem[] = [
{
id: 1,
title: 'Купить хлеба',
description: 'Сходить и купить немного хлеба, а то жена заклевала уже.',
isComplete: true,
},
{
id: 2,
title: 'Купить селедки',
description: 'Сходить и купить селедочку, а то закусывать надо.',
isComplete: false,
},
{
id: 3,
title: 'Купить пива',
description: 'Просто купить холодненького и освежающего.',
isComplete: false,
},
{
id: 4,
title: 'Связать носки',
description: 'Да, надо готовиться к зиме.',
isComplete: false,
},
{
id: 5,
title: 'Погладить кота',
description: 'Ну а почему бы и нет?!.',
isComplete: false,
},
{
id: 6,
title: 'Засунуть руку в унитаз',
description: 'Зачем и нет?!.',
isComplete: false,
},
];
constructor() {
// this.todoList = JSON.parse(localStorage.getItem('todoList'));
}
getAllTodos(): TodoItem[] {
return this.todoList;
}
deleteTodo(id: number): void {
const todoItemIndex = this.todoList.findIndex((todo) => todo.id === id);
this.todoList.splice(todoItemIndex, 1);
}
completeTodo(id: number) {
this.todoList = this.todoList.map((todo) => {
if (todo.id === id) {
todo.isComplete = !todo.isComplete;
return todo;
}
return todo;
});
}
createTodo(todo: TodoItem): void {
this.todoList.push(todo);
}
updateTodo(id: number) {}
}
todo-item.component.html
<li
class="flex flex-row border rounded-lg p-3 cursor-pointer my-3 {{
todoItem.isComplete ? 'isComplete' : ''
}}"
(click)="toggleComplete(todoItem.id)"
>
<div class="flex flex-col w-3/4">
<h3>{{ todoItem.title }}</h3>
<p class="text-xs text-gray-400">
{{ todoItem.description }}
</p>
</div>
<div class="flex flex-col justify-center w-1/4">
<button
class="flex items-center justify-center rounded-lg text-white bg-blue-700 px-3 py-2 h-1/2"
(click)="editTodo(todoItem.id)"
>
Edit task
</button>
<button
(click)="deleteTodo(todoItem.id)"
class="flex items-center justify-center rounded-lg text-white bg-red-700 px-3 py-2 h-1/2 mt-3"
>
{{ todoItem.id }}
Delete task
</button>
</div>
</li>
todo-item.component.ts
import { Component, inject, Input } from '@angular/core';
import { TodoItem } from '../interfaces/todo-item';
import { TodosService } from '../services/todos.service';
@Component({
selector: 'app-todo-item',
standalone: true,
imports: [],
templateUrl: './todo-item.component.html',
styleUrl: './todo-item.component.css',
})
export class TodoItemComponent {
@Input() todoItem!: TodoItem;
todosService: TodosService = inject(TodosService);
deleteTodo(id: number): void {
this.todosService.deleteTodo(id);
}
toggleComplete(id: number): void {
this.todosService.completeTodo(id);
}
editTodo(id: number): void {
this.todosService.updateTodo(id);
}
}
所以第一次点击效果很好。它删除待办事项并重新渲染组件。下一次单击仅从数组中删除项目,但不会发生重新渲染。为什么?
我尝试执行
this.todoList = this.todoList.filter(todo => todo.id !== id)
功能。它也只更新数组状态,但不会发生重新渲染。我做错了什么?
当修改数组的内部属性时,对该数组的实际内存引用不会改变。所以 ngFor 无法知道变化是否发生了。
您可以在这里进行两个修复。
进行任何修改或删除后,只需使用数组解构来创建数组的浅表副本,以便
ngFor
知道刷新视图。
getAllTodos(): TodoItem[] {
return this.todoList;
}
deleteTodo(id: number): void {
const todoItemIndex = this.todoList.findIndex((todo) => todo.id === id);
this.todoList.splice(todoItemIndex, 1);
this.todoList = [ ...this.todoList ]; // <- changed here!
}
completeTodo(id: number) {
this.todoList = this.todoList.map((todo) => {
if (todo.id === id) {
todo.isComplete = !todo.isComplete;
return todo;
}
return todo;
});
this.todoList = [ ...this.todoList ]; // <- changed here!
}
createTodo(todo: TodoItem): void {
this.todoList.push(todo);
this.todoList = [ ...this.todoList ]; // <- changed here!
}
updateTodo(id: number) {}