【问题标题】:Angular 2 / 4 Observables Unwanted Two-Way BindingAngular 2 / 4 Observables 不需要的双向绑定
【发布时间】:2017-11-06 11:27:37
【问题描述】:

(我正在重构我的问题,因为我认为第一个问题非常令人困惑......)

我正试图弄清楚 Observables 在 Angular 2 / 4 中是如何工作的。具体来说,我想在组件初始化时订阅服务的 Observable,然后在组件的生命周期后期我想在没有它的情况下修改数据影响 observable 或其他订阅者。我将数据存储在组件上的变量中,但是当我修改它时,Observable 的其他订阅者也会显示更改。

在我的代码中,有三个可观察对象:客户、项目和用户。现在我只是想修改 Observable 项目中的数据。我将数据用作 ng2-ui 自动完成的来源,所以我不能按照下面评论中的建议使用 *ngFor。

common.service.ts(创建可观察对象)

import { Observable } from 'rxjs'
import { BehaviorSubject } from 'rxjs';

export class UserService {
  public clients: BehaviorSubject<any> = new BehaviorSubject(null);
  public projects: BehaviorSubject<any> = new BehaviorSubject(null);
  public user: BehaviorSubject<any> = new BehaviorSubject(null);

  constructor(){};

}

login.ts(订阅 Observable,从 API 获取数据,然后将其传递给 Observables)

ngOnInit() {
  this.userService.clients.subscribe();
  this.userService.projects.subscribe();
}

userLogin() {
  this.commonService.request('login', 'post', '', {password: this.password, email: this.email})
    .then((response:any) => {
      if(response.token) {
        this.configService.token = response.token;
        if(response.clients) this.userService.clients.next(response.clients);
        if(response.projects) this.userService.projects.next(response.projects);
        this.configService.loggedIn = true;
        this.router.navigate(['dashboard']);
      }
    })
}

component.ts(订阅,从 Observable 中获取数据然后修改)

ngOnInit() {
  this.userService.clients.subscribe((clients) => {
    this.clients = clients;
  });
  this.userService.projects.subscribe((projects) => {
    this.projects = projects;
  });
  this.filteredProjects = this.projects;
  this.filteredClients = this.clients;
}

filterProjects(client) { // When a client is selected
  this.filteredProjects.forEach((project) => {
    if(client.projects.indexOf(project._id) == -1) {
      filteredProjects.splice(project._id, 1) // this splices the filteredProjects array, but also this.projects and any other subscriptions to the observable in the app.
    }
  });
}

当我过滤 this.filteredProjects 时,this.projects 也会被修改。我可以通过两个对象的 console.logs 看到这一点,也因为另一个组件正在订阅可观察的项目,而这个另一个组件也显示了更改。

但是,如果我不过滤 this.filteredProjects,而只是说 this.filteredProjects = [];,那么 this.projects 将保持不变。

如何在不影响可观察对象或其其他订阅者的情况下修改可观察对象的数据?

【问题讨论】:

    标签: angular observable angular2-observables


    【解决方案1】:

    我不完全确定您通过查看您的代码尝试完成什么,但我会尝试为您提供一个更好的方向来实现您尝试做的事情。

    根据我的理解,您需要一个通用的可观察对象来保存您的项目。我假设你已经得到了这个工作(虽然你没有在你的代码中)。 现在,在您的组件中,您希望首先获得对它的订阅。有几种方法可以使用订阅,我看到你尝试做的方式是订阅它,这种方法的问题是它会花费你很多工作。首先,您需要处理项目数组的副本,因为现在您说您更改了所有代码中的项目,因为您在任何地方都使用相同项目数组的引用(有获取副本的方法有很多种,其中一种方法是使用带有空数组的 concat。

    完成此操作后,您还需要知道用户选择了哪个客户端,因此当再次发出订阅时(我假设您所说的项目列表可以在此组件之外更改)您将拥有再次获取新副本,然后再次过滤。这可能有效,并且最接近您的描述。

    我认为您还应该寻找一种更好的方法来做到这一点,例如在 html 中使用带有异步管道的 ngFor 来迭代订阅中的项目 (async pipe, can be used with ngfor。接下来您可以在 html 中使用自定义过滤器来过滤所选客户端的结果。

    【讨论】:

    • 感谢您的回答。在另一个组件中,我订阅了 observable,从 http GET 获取项目和客户,并使用 this.userService.projects.next(response.projects); 分配值,这是有效的。我会研究复制 observables 值的其他方法,因为我仍然认为这是最好的方法,我会用其他一些细节更新我的 OP,希望能更好地解释。
    • 我明白了,如果您认为后一种方法更适合您,那么请尝试遵循我回答的第一种方法
    猜你喜欢
    • 1970-01-01
    • 2017-04-29
    • 1970-01-01
    • 1970-01-01
    • 2017-02-18
    • 1970-01-01
    • 1970-01-01
    • 2017-11-02
    • 1970-01-01
    相关资源
    最近更新 更多