在 angular 中使用 Subjects/event 发射器进行跨组件通信时出现奇怪的行为?

Weird behavior while using Subjects/event emitters in services for cross component communication in angular?

我想了解 observable、subjects 和 behavior subject 是如何工作的(读了很多文章,看了很多视频,但我还是不清楚,因为我没能解释这种行为)所以我创建了这个简单的例子,并得到了意想不到的行为。 我有两个组件,一个 父组件 和一个 子组件

父组件显示一个包含照片名称的列表,并带有显示详细信息的按钮。单击此按钮后,它将带我们进入子组件,我希望在其中显示单张照片以及详细信息。所以,这就是想法。

我使用了一个有主题的服务。现在,每当单击父组件中的按钮时,我都会从主题中发出一个值。我想在我的子组件中捕获这个值,所以我订阅它。

有一个奇怪的行为-- 对于第一次点击,我没有在我的子组件中看到任何数据。 第二次单击子组件中的单个值。 第三次单击子组件中的两个值, 等等....

这是我的组件--

parent.component.ts

export class ParentComponent implements OnInit {
  photoList = [
    {
      albumId: 1,
      id: 1,
      title: "accusamus beatae ad facilis cum similique qui sunt",
      url: "https://via.placeholder.com/600/92c952",
      thumbnailUrl: "https://via.placeholder.com/150/92c952",
    },
    {
      albumId: 1,
      id: 2,
      title: "reprehenderit est deserunt velit ipsam",
      url: "https://via.placeholder.com/600/771796",
      thumbnailUrl: "https://via.placeholder.com/150/771796",
    },
    {
      albumId: 1,
      id: 3,
      title: "officia porro iure quia iusto qui ipsa ut modi",
      url: "https://via.placeholder.com/600/24f355",
      thumbnailUrl: "https://via.placeholder.com/150/24f355",
    },
  ];
  constructor(private _talkService: TalkService, private router: Router) {}

  ngOnInit() {}

  displayName(id, url, thumbnailUrl) {
    console.log({ id, url, thumbnailUrl });

    //this._talkService.talk.emit({ url, thumbnailUrl });
    this._talkService.talk.next({ id, url, thumbnailUrl });
    this.router.navigate(["/photo"]);
  }
}

child.component.ts

export class ChildComponent implements OnInit {
  constructor(private _talkService: TalkService) {}

  ngOnInit() {
    console.log("child component created");
    this._talkService.talk.subscribe((data) => {
      console.log(data);
    });
  }
}

talk.service.ts

@Injectable({
  providedIn: "root",
})
export class TalkService {
  // talk = new EventEmitter();
  talk = new Subject();
  constructor() {}
}

输出控制台日志

这三个我都用过--

事件发射器-->与描述的行为相同 受试者-->与描述的行为相同 Behavior Subjects--> 我也得到了第一个值(因为它帮助我们得到之前发出的值,我理解那部分)。也欢迎在这里详细解释。

我原以为每次点击都有一个值,但事实并非如此。有人可以向我解释这种行为吗?这一定是 observable 工作的方式,我无法得到它。

这是我的 github 仓库的 link--

source code github

听起来像是典型的内存泄漏。每次您订阅 talkService.talk 时,您都在创建一个只有在取消订阅后才会被清理的订阅。因此,即使当您返回到父组件时,子组件看起来像是被销毁了,订阅仍然存在,并且每次 talk 主题发出新值时都会执行控制台日志。当 Child 组件被销毁时,您应该取消订阅。确保取消订阅的一种简单方法是使用 html 模板中的 async 管道。

child.component.ts

export class ChildComponent implements OnInit {
  data$: Observable<any> = this.talkService.talk;

  constructor(private talkService: TalkService) {}
}

child.component.html

<pre>{{ data$ | async }}</pre>

此外,您可以切换回使用 BehaviorSubject,因为子组件将在从父组件发出值后订阅 talk