繁体   English   中英

在Angular 2服务中绑定到数据对象的正确方法?

[英]Proper way to bind to data object in Angular 2 service?

我正在建立一个角度2应用程序。 自发布以来,文档发生了很大的变化,引起了混乱。 我能做的最好的事情就是解释我想要做的事情(在Angular 1中这很容易)并希望有人可以帮助我。

我已经使用JWT创建了一个登录服务。 登录成功后,我返回一个用户对象。

我有一个loginComponent(将数据绑定到模板)和loginService(处理https调用)

我有一个维护用户对象的userService。

我有一个userComponent,用于呈现用户数据。

问题是,一旦用户登录,我不清楚让userService在名为“user”的对象中检索新数据的最佳方法,然后userComponent更新模板上的用户对象。 只需将观察者放在userService.user对象上,就可以轻松实现角度1。

我尝试输入和输出无效,eventEmitters,Observables和getter and setters。 getter和setter工作,但强迫我将所有内容存储在“val()”中

有人可以告诉我实现这个目标的最佳方法吗?

  1. 用户组件使用user.firstName,user.lastName等呈现模板。
  2. 最初用户如果是空对象
  3. 登录服务需要设置UserService.user
  4. userComponent需要检测更改并更新DOM。

提前致谢!

如果我没有错,那么您正在寻找一种方法来“监听” UserService.user更改,以便在UserComponent进行适当的更新。 使用Subject (或BehaviorSubject )很容易做到这一点。

- 在UserService ,声明类型为Subject<User>的属性user

user: Subject<User> = new Subject();

- 将其暴露在外面作为可观察的:

user$: Observable<User>
...
this.user$ = this.user.asObservable();

-Login函数将更新私有user Subject。

login(userName: string, password: string) {
  //...
  this.user.next(new User("First name", "Last name"));
}

- 在UserComponent ,订阅UserServiveuser$ observable以更新视图。

this.userService.user$.subscribe((userData) => {this.user = userData;});

- 在您看来,只需使用字符串插值:

{{user?.firstName}} {{user?.lastName}}

这是工作的插件: http ://plnkr.co/edit/qUR0spZL9hgZkBe8PHw4?p = preview

您可以采取两种不同的方法:

1.通过JavaScript引用类型共享数据

如果在UserService中创建对象

@Injectable()
export class UserService {
   public user = new User();

然后,您可以通过它作为JavaScript引用类型来共享该对象。 注入UserService的任何其他服务或组件都可以访问该user对象。 只要您在服务中仅修改原始对象 (即,不指定新对象),

   updateUser(user:User) {
       this.user.firstName = user.firstName;
       this.user.lastName  = user.lastName;
   }

所有视图都会在更改后自动更新并显示新数据(因为Angular更改检测的工作方式)。 没有任何类似Angular 1的观察者

这是一个示例的plunker

在plunker中,它具有共享data对象,而不是共享user对象。 您可以单击一个更改数据按钮,该按钮将调用服务上的changeData()方法。 您可以看到,当服务更改其data属性时,AppComponent的视图会自动更新。 您不必编写任何代码来使其工作 - 不需要getter,setter,Input,Output / EventEmitter或Observable。

视图更新自动发生,因为(默认情况下)每次猴子修补的异步事件触发(例如按钮单击)时,角度更改检测会检查所有模板绑定(如{{data.prop1}} )。

2.使用RxJS“ 推送 ”数据

@HarryNinh在他的回答中说得非常好。 另请参阅Cookbook主题父级和子级通过服务进行通信 它显示了如何使用主题来促进“在一个家庭中”的通信。

我建议使用BehaviorSubject而不是Subject,因为BehaviorSubject具有“当前值”的概念,这可能适用于此处。 考虑一下,如果使用路由和(基于某些用户操作)移动到新路由并创建新组件,您可能希望新组件能够检查用户的“当前值”。 你需要一个BehaviorSubject来完成这项工作。 如果使用常规Subject,则新组件将无法检索当前值,因为Subject的订阅者只能获取新发出的值。


那么,我们应该使用方法1还是2.? 像往常一样,“它取决于”。 方法1.代码少得多,您不需要了解RxJS(但您需要了解JavaScript引用类型)。 方法2.这些天风靡一时。

方法2.也可以比1.更有效,但是因为Angular的默认变化检测策略是“检查所有组件”,你需要使用OnPush变化检测策略和markForCheck() (我不打算进入如何在这里使用这些)使其比方法1更有效。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM