我有一个TODO应用程序,它使用主题即服务方法来进行状态管理.

我的待办事项服务如下所示

import { Injectable } from '@angular/core';
import { Todo } from './todo.model';
import { HttpClient } from '@angular/common/http';
import { Observable, BehaviorSubject, map, pipe } from 'rxjs';

@Injectable()
export class TodosService {
  private todos$ = new BehaviorSubject<Todo[]>([]);
  constructor(private http: HttpClient) {
    this.http
      .get<Todo[]>('https://jsonplaceholder.typicode.com/users/1/todos')
      .subscribe((todos) => {
        this.todos$.next(todos);
      });
  }

  public getTodos(): Observable<Todo[]> {
    return this.todos$;
  }

  public getCompletedTodos(): Observable<Todo[]> {
    return this.todos$.pipe(
      map((todos) => todos.filter((todo) => todo.completed))
    );
  }

  public addTodo(event: string) {
    const newArray: Todo[] = [
      ...this.todos$.value,
      {
        userId: 1,
        id: this.todos$.value.length,
        title: event,
        completed: false,
      },
    ];
    this.todos$.next(newArray);
  }
}

我的Add-Todo组件如下所示.

import 'zone.js/dist/zone';
import { Component } from '@angular/core';
import { TodosService } from './todo.service';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';

@Component({
  selector: 'app-add-todo',
  standalone: true,
  imports: [CommonModule, FormsModule],
  providers: [TodosService],
  template: `
    <label>Add Todo</label>
    <input type="text" [(ngModel)]="todo" />
    <button (click)="addNewTodo()">Submit</button>
  `,
})
export class AddTodo {
  todo: string = '';
  constructor(private todoService: TodosService) {}

  addNewTodo() {
    this.todoService.addTodo(this.todo);
    this.todo = '';
  }

  ngOnInit() {}
}

我知道组件正在调用我的addTodo方法,因为我可以通过控制台记录newArray值,并在try 添加新值时看到它.但出于某种原因,我的新待办事项没有展示出来.

更奇怪的是,当我在我的服务的构造函数中调用addTodo时,它工作得很好.这样做时,我的显示待办事项的组件就会正确更新.

  constructor(private http: HttpClient) {
    this.http
      .get<Todo[]>('https://jsonplaceholder.typicode.com/users/1/todos')
      .subscribe((todos) => {
        this.todos$.next(todos);
      });

      setTimeout(()=> {
        this.addTodo('Todo from inside setTimeout')
      }, 3000)
  }

Todo App

那么,为什么我的list-todo组件在从组件调用addTodo时不更新,而不是在服务本身内部更新呢?

我创造了一个stackblitz demo

推荐答案

正如@BizzyBob在 comments 中提到的,如果您在组件级别提供TodosService,则每个组件将获得其自己的TodosService实例,并且它们之间将不存在共享状态.

在您的例子中,您可以通过在main.tsApp组件中提供TodosService并从独立组件中删除各个提供程序数组来解决此问题.

您的App分量将如下所示:

@Component({
  selector: 'my-app',
  standalone: true,
  imports: [
    CommonModule,
    TodoList,
    TodoListSubscribe,
    HttpClientModule,
    AddTodo,
  ],
  providers: [TodosService],
  template: `
    <app-todo-list></app-todo-list>
    <app-add-todo></app-add-todo>
  `,
})
export class App {}

Angular相关问答推荐

PrimeNG侧栏清除primeNG消息.为什么?

为什么我的自定义.d.ts不起作用?LeaderLine不是构造函数

对子router-outlet 应用主机样式

有Angular react 形式的输入用货币管

根据环境变量动态加载Angular templateUrl

当try 关闭浏览器选项卡时显示alert 时,我是否可以捕获用户是否取消警告

如何处理后端删除元素后元素列表的刷新

对象中的值丢失 angular ngrx

路由链接不在 Ionic 中执行

console.log 返回 api 数据但 ERROR TypeError: Cannot read properties of undefined reading 'name'

我想将一个对象传递给一个子组件.我做了一切,但没有任何效果. (Angular )

带有重定向的Angular 2 AuthGuard服务?

带有 Angular 2 的 Django

如何在 Angular Cli 中生成 .angular-cli.json 文件?

将外部 CSS 加载到组件中

Angular @NGRX中这三个点的含义是什么

如何使用 Angular 6 工作的 ngModel 创建自定义输入组件?

我应该在 Angular 4+ 应用程序中 for each 组件创建一个模块吗?

Angular2:子组件访问父类变量/函数

如何在 Angular 中使用 router.navigateByUrl 和 router.navigate