为什么在 Angular 服务中删除期间更新状态不会重新渲染组件?

问题描述 投票:0回答:1

我有两个组件

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)
功能。它也只更新数组状态,但不会发生重新渲染。我做错了什么?

javascript angular components state render
1个回答
0
投票

当修改数组的内部属性时,对该数组的实际内存引用不会改变。所以 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) {}
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.