[英]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()”中
有人可以告诉我实现这个目标的最佳方法吗?
提前致谢!
如果我没有错,那么您正在寻找一种方法来“监听” 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
,订阅UserServive
的user$ 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.