2016-08-13 58 views
5

我正在構建一個角度2應用程序。自發布以來,文檔發生了很大變化,造成了混亂。我能做的最好的事情就是解釋我想要做什麼(Angular 1中很容易),並希望有人能幫助我。在Angular 2服務中綁定數據對象的正確方法?

我已經使用JWT創建了一個登錄服務。 登錄成功後,我返回一個用戶對象。

我有一個loginComponent(數據綁定到模板)和login服務(其處理HTTPS呼叫)

我有保持用戶對象userService。

我有一個userComponent呈現用戶數據。

問題是,一旦用戶登錄,我不清楚讓userService檢索名爲「user」的對象中的新數據的最佳方法,然後userComponent更新模板上的用戶對象。簡單地通過在userService.user對象上放置一個觀察器就可以輕鬆實現角度1。

我試過輸入和輸出無效,eventEmitters,Observable和getters和setters。 getters和setters工作,但迫使我將所有內容都存儲在「val()」中。有人可以告訴我實現此目的的最佳方式嗎?

  1. 用戶組件使模板與user.firstName,user.lastName等
  2. 最初用戶如果一個空對象
  3. 登錄服務需要設置UserService.user
  4. 的userComponent需要檢測更改並更新DOM。

感謝ADVANCE!

回答

8

如果我沒有錯,您正在尋找一種方法來'聆聽'您的UserService.user中的更改,以便在您的UserComponent中進行適當的更新。用Subject(或BehaviorSubject)這樣做很容易。

- 在您的UserService中,聲明屬性user的類型爲Subject<User>

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

-Expose它外面觀察到:

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,訂閱UserServiveuser$ observable更新視圖。

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

- 在你看來,只需使用字符串插值:

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

這裏是工作plunker:http://plnkr.co/edit/qUR0spZL9hgZkBe8PHw4?p=preview

+0

所以基本上這與角1中的觀察者一樣嗎?數據在服務中發生變化時,視圖會更新? –

+0

另外,我們的目的是什麼?分數?可選變量? –

+0

是的。你可以在提供的運動中玩弄它。存在操作符('?.')用於安全地檢索可空對象的屬性值。如果'user'爲null或未定義,這將輕輕地將空字符串渲染爲標記,而使用'user.firstName'會引發一些錯誤。在笨蛋中,我用'ngIf'來包裝所有東西,所以我不需要它。 –

4

有兩種完全不同的方法,你可以採取:

1.通過JavaScript參考類型共享數據

如果您在UserService

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

創建一個對象,你可以再僅僅憑藉這是一個JavaScript引用類型的共享對象。注入UserService的任何其他服務或組件都將有權訪問該對象。只要你只修改原始對象在服務改變後(即你不分配一個新的對象),

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

你的視圖會自動更新,顯示新數據(因爲角度變化檢測的方式)。有no need for any Angular 1-like watchers

下面是一個示例plunker

在闖入者中,而不是共享的user對象,它具有共享的data對象。有一個更改數據按鈕,您可以單擊該按鈕將調用服務上的changeData()方法。您可以看到,當服務更改其data屬性時,AppComponent的視圖會自動更新。您不必編寫任何代碼來實現此功能 - 不需要getter,setter,Input,Output/EventEmitter或Observable。

視圖更新自動發生,因爲(默認情況下)角度更改檢測每次發生猴子修補的異步事件(例如按鈕單擊)時檢查所有模板綁定(如{{data.prop1}})。

2. 「Push」 數據使用RxJS

@HarryNinh在他的回答涵蓋這很好。另請參閱食譜主題Parent and children communicate via a service。它展示瞭如何使用主題來促進「家庭內部」的溝通。

我建議使用BehaviorSubject而不是主題,因爲BehaviorSubject具有「當前值」的概念,這在此可能適用。考慮一下,如果您使用路由和(基於某些用戶操作)移動到新路線並創建新組件,則可能希望該新組件能夠檢查用戶的「當前值」。你需要一個BehaviorSubject來完成這個工作。如果您使用常規主題,新組件將無法檢索當前值,因爲主題的訂閱者只能獲取新發布的值。


那麼,我們應該使用方法1還是方法2?像往常一樣,「這取決於」。方法1是少了很多代碼,並且您不需要了解RxJS(但您確實需要了解JavaScript引用類型)。方法2.這些日子都是憤怒。

方法2也可能比1更有效,但由於Angular的默認更改檢測策略是「檢查所有組件」,因此您需要使用OnPush更改檢測策略和markForCheck()(我不打算進入如何使用這裏),使其比方法1更有效。

+0

嗨,你可以檢查一下嗎? https://stackoverflow.com/questions/48355599/loading-large-array-in-oi-select-takes-too-much-of-time-in-angularjs – Sudarshan

相關問題