首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Angular - reusing a component?

Angular - reusing a component?
EN

Stack Overflow用户
提问于 2017-11-05 22:35:39
回答 2查看 825关注 0票数 0

所以,这就是我的用例:我从rest API获取一个observable,然后通过在模板中使用async来获取数据。单击时,我将获得特定用户的ID,然后使用该用户的数据填写表单。为了实现后者,我重用现有的观察值并过滤数据,然后订阅它。我想知道我的方法是否正确,因为我认为当我点击“编辑”来填写表单时,应用程序太慢了,所以我猜我在这里创建了太多的订阅或诸如此类的东西?

另外,为了便于讨论,我创建了两个可观察对象(userusers),其中一个(user)获得了对另一个(users)的“引用”,然后它用async显示在模板中,同时我还订阅了它并将其设置为“常规”变量。这是一个问题吗?使用async显示可观察对象并订阅它?

下面是代码,因为我的问题可能有点令人困惑:

代码语言:javascript
复制
//our root app component
import {Component, NgModule, VERSION, OnInit, OnDestroy} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import { HttpClientModule } from '@angular/common/http';
import { ReactiveFormsModule } from '@angular/forms';
import { Observable }     from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';

import 'rxjs/add/operator/map';
import 'rxjs/add/operator/find';
import 'rxjs/add/operator/takeUntil';

import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';

import { UserService } from './service';

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Hello {{name}}</h2>
      <div>
        {{user | async | json}}
        {{selected | json}}
      </div>
      <div *ngFor="let u of users | async">
        {{u.first_name}} {{u.last_name}}
        <br />
        <img [src]="u.avatar" />
        <br />
        <br />
        <a (click)="edit(u.id)">Edit</a>
        <br />
        <br />
      </div>
      <div>
        <form [formGroup]="userForm" (ngSubmit)="onSubmit()" novalidate>
            <input type="text" formControlName="first_name" />
            <input type="text" formControlName="last_name" />
        </form>
        <p>userForm value: {{ userForm.value | json}}</p>
        <p>validity: {{ userForm.valid }}</p>
      </div>
    </div>
  `,
  styles: ['a { cursor: pointer; }']
})
export class App implements OnInit, OnDestroy {
  users: Observable<any>;
  user: Observable<any>;
  destroy$: Subject<boolean> = new Subject<boolean>();

  name:string;
  userForm: FormGroup;

  constructor(private fb: FormBuilder, private service: UserService) {
    this.name = `Angular! v${VERSION.full}`;
    this.createForm();
  }

  createForm() {
    this.userForm = this.fb.group({
      first_name: ['', {updateOn: 'blur', validators: [Validators.required, Validators.minLength(2), Validators.maxLength(10)]}],
      last_name: ['', [Validators.required, Validators.minLength(2), Validators.maxLength(20)]]
    })
  }

  edit(id) {
    this.user =  this.users.map(x => x.find(x => x.id === +id));

    this.user.takeUntil(this.destroy$).subscribe(u => {
      console.log(u);
      this.selected = u;

      this.userForm.patchValue({
        first_name: u.first_name,
        last_name: u.last_name
      });

    });
  }

  ngOnInit() {
    console.clear();
    console.log('hello world');

    this.users = this.service.all();
  }

  ngOnDestroy() {
    this.destroy$.next(true);
    this.destroy$.unsubscribe();
  }
}

@NgModule({
  imports: [ BrowserModule, HttpClientModule, ReactiveFormsModule ],
  providers: [UserService],
  declarations: [ App ],
  bootstrap: [ App ]
})
export class AppModule {}

下面是链接:http://plnkr.co/edit/F0dheIdgoNNw53hNVjZm?p=preview

EN

回答 2

Stack Overflow用户

发布于 2017-11-06 05:42:29

假设您想要使用可观察性来完成此任务。虽然在Leon的答案中有更直接的方法,但为了学习可观察性,让我们这样做:-)

您正在使用异步管道在模板中订阅user observable,但也在编辑方法中订阅。edit方法中的订阅永远不会取消订阅,因此存在内存泄漏。

此外,每次单击用户并让异步管道输入模板以重新订阅时,您都会重新定义this.user observable。这会导致另一个内存泄漏,因为异步管道没有关于应该取消订阅的重写可观察对象的线索。

这并不是你应该如何组成你的可观察到的流。首先,您应该定义可观察的数据转换。

当我查看您的应用程序时,您有两个数据/事件来源:

服务

  • 中的
  1. 用户单击编辑按钮

用户只能从服务中观察到。Clicks应该是真正的Subject。因为在编辑时,您应该发出被单击的userId (可观察),并通过显示用户详细信息(观察者行为)对此单击做出反应。

代码语言:javascript
复制
editClick: Subject<number> = new Subject<number>;

因此,让我们定义一下user observable应该是什么样子(所有这些代码都是用ngOnInit编写的):

代码语言:javascript
复制
this.users = this.service.all().shareReplay();
this.user = this.editClick
    .switchMapTo(this.users, (userId, users) => ({ userId, users}))
    .map(x => x.users.find(user => user.id === +x.userId))
    .do((u) => {
        console.log(u);
        this.selected = u;

        this.userForm.patchValue({
            first_name: u.first_name,
            last_name: u.last_name
      });
   });

在这里,我定义了基于editClick的用户可观察性-这是我稍后将从中获取id的地方。使用switchMapTo,我将editClick中的users、observable和id组合为object,稍后我将使用它来过滤被单击的用户。

现在如何在onEdit方法中触发editClick?只需在每次单击时发出userId,如下所示:

代码语言:javascript
复制
edit(id) {
    this.editClick.next(id);
}

注意我是如何在ngOnInit中定义数据流的。一开始只有一次。没有娱乐之类的。我有两个观察点要订阅:

用于显示用户的

  1. users用于显示详细信息的list
  2. user -这将在每次触发editClick

时发出

此外,模板中只有订阅,因此没有内存泄漏,因为async管道将为您管理unsubscribe

票数 1
EN

Stack Overflow用户

发布于 2017-11-06 00:42:08

您可以通过传递整个用户而不仅仅是id来极大地简化edit方法。

代码语言:javascript
复制
<a (click)="edit(u)">Edit</a>

edit(user) {
  this.selected = user;

  this.userForm.patchValue({
    first_name: user.first_name,
    last_name: user.last_name
  });
}

至于多次调用service.all()会导致多个订阅和多个后台调用。

如果您想多次调用它,请使用.share() rxjs操作符。这将在可观察对象周围创建一个包装器主题,该主题将在每次调用时返回相同的值。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47122758

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档