首页 > 解决方案 > BehaviorSubject:为什么不使用 next 就可以工作

问题描述

我有一个 Angular 应用程序,并为我的联系人列表创建了一个类,其中包括:

export interface Contact {
    id: number;
    name: string;
    address: string;
}

export class ContactList {
    private contactList: Contact[];
    private contactNumber: number;

public getContactList(): Contact[] {
        return this.contactList;
    }

// Methods to add, modify and remove a contact
}

然后我有一个实例化这个类的服务,创建一个BehaviorSubject来与其他组件共享它,并有一些公共方法。

export class ContactListService {

  public contactList: ContactList;
  private contactList$: BehaviorSubject<Contact[]>;

  constructor() {
    this.contactList = new ContactList(FAKE_CONTACTS);
    this.contactList$ = new BehaviorSubject<Contact[]>(this.contactList.getContactList());
  }

  public getContactList(): BehaviorSubject<Contact[]> {
    return this.contactList$;
  }

  public deleteContact(contactId: number): void {
    this.contactList.deleteContact(contactId);
  }

  public addContact(newName: string, newAddress: string): void {
    this.contactList.addContact(newName, newAddress);
  }

  public modifyContact(contactId: number, newName?: string, newAddress?: string): void {
    this.contactList.modifyContact(contactId, newName, newAddress);
  }
}

然后,在一个组件中,我订阅了BehaviorSubject并将值影响到我的组件的一个属性。

ngOnInit() {
    this.contactListSubscription = this.contactListService.getContactList().subscribe((newContactList) => {
      this.contactList = newContactList;
    });
  }

所以它正在工作(即,当我通过服务执行操作时,一切都会更新)。但我不明白的是,订阅的内容(即。this.contactList = newContactList)只在订阅时执行一次,而不是每次发生动作时执行。即使我通过 contactListService 方法更改内容。即使我取消订阅,比如订阅后 2 秒(例如使用 setTimeout),取消订阅后内容始终是最新的......

起初,我什至不明白为什么它在服务中工作而不执行contactList$.next(this.contactList.getContactList())修改对象的每个操作。

所以看起来我传递了一些引用而不是类的内容?我想我不明白BehaviorSubject是如何工作的!

标签: angularrxjsbehaviorsubject

解决方案


JavaScript总是传递对对象的引用。

因此,contactList组件中的数组是对存储在您的ContactList.contactList属性中的相同、唯一数组的引用。

因此,您修改了数组,组件引用了这个修改后的数组,Angular 检测到数组中的更改,并将更改应用到 DOM。

ContactList如果方法中的方法用另一个(修改后的副本)替换了数组,它就不再起作用了,例如

this.contactList = [this.contactList..., newContact]

在这种情况下,组件将继续引用先前未修改的数组。

用代码来说明:

service.contactList = ['John', 'Mary'];
component.contactList = service.contactList; // the exact, same array

service.contactList.push('Helen'); // add an element to the unique array
console.log(component.contactList); // logs John, Mary, Helen: it's the same, unique array

service.contactList = ['Jack']; // now the service references a second, different array
console.log(component.contactList); // Still logs John, Mary, Helen

推荐阅读