我正在构建一个角度2应用程序。自发布以来,文档发生了很大的变化,引起了混乱。我能做的最好的事情就是解释我想要做的事情(在Angular 1中这很容易)并希望有人可以帮助我。
我使用JWT创建了一个登录服务。 登录成功后,我返回一个用户对象。
我有一个loginComponent(将数据绑定到模板)和loginService(处理https调用)
我有一个维护用户对象的userService。
我有一个userComponent,用于呈现用户数据。
问题是,一旦用户登录,我不清楚让userService在名为" user"的对象中检索新数据的最佳方法,然后userComponent更新其用户对象模板。只需将观察者放在userService.user对象上,就可以轻松实现角度1。
我尝试输入和输出无效,eventEmitters,Observables和getter and setter。 getter和setter工作,但强迫我将所有内容存储在" val()"
有人可以告诉我实现这个目标的最佳途径吗?
先谢谢!
答案 0 :(得分:8)
如果我没有错,那么你正在寻找一种方法来聆听'要更改UserService.user
,以便在UserComponent
中进行适当的更新。使用Subject
(或BehaviorSubject
)很容易做到这一点。
- 在UserService
中,声明属性user
,其类型为Subject<User>
。
user: Subject<User> = new Subject();
- 将其暴露在外面作为可观察的:
user$: Observable<User>
...
this.user$ = this.user.asObservable();
-Login函数将更新私人user
主题。
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}}
答案 1 :(得分:4)
您可以采取两种不同的方法:
<强> 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更改检测的工作方式)。有no need for any Angular 1-like watchers。
以下是plunker的示例。
在plunker中,它有一个共享的user
对象,而不是共享的data
对象。您可以单击更改数据按钮,该按钮将在服务上调用changeData()
方法。您可以看到,当服务更改其data
属性时,AppComponent的视图会自动更新。您不必编写任何代码来使其工作 - 不需要getter,setter,Input,Output / EventEmitter或Observable。
视图更新自动发生,因为(默认情况下)角度更改检测会在每次启动猴子修补的异步事件(例如按钮单击)时检查所有模板绑定(如{{data.prop1}}
)。
<强> 2。 “Push”数据使用RxJS
@HarryNinh在他的回答中说得很清楚。另见Cookbook主题Parent and children communicate via a service。它显示了如何使用主题来促进“在一个家庭中”的沟通。我建议使用BehaviorSubject而不是Subject,因为BehaviorSubject具有“当前值”的概念,这可能适用于此处。考虑一下,如果使用路由和(基于某些用户操作)移动到新路由并创建新组件,您可能希望新组件能够检查用户的“当前值”。你需要一个BehaviorSubject来完成这项工作。如果使用常规Subject,则新组件将无法检索当前值,因为Subject的订阅者只能获取新发出的值。
那么,我们应该使用方法1还是2.?像往常一样,“它取决于”。方法1.代码少得多,您不需要了解RxJS(但您需要了解JavaScript引用类型)。方法2.这些日子风靡一时。
方法2.也可能比1.更有效,但由于Angular的默认变更检测策略是“检查所有组件”,您需要使用OnPush
更改检测策略和markForCheck()
(我不会在这里讨论如何使用它们)使其比方法1更有效。