[英]How to share data between angular's services and components?
如何實時綁定服務和組件之間的數據。
讓我們假設isAuthenticated
是身份驗證服務的公共變量,該變量影響組件中的某些視圖。 我的問題是如何訂閱isAuthenticated
變量?
服務:
import { Injectable } from '@angular/core';
@Injectable()
export class Authentication {
isAuthenticated:boolean = false;
login() {
localStorage.setItem('access_token', 'true');
this.isAuthenticated = true;
}
}
成分:
...
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
private isAuthenticated:boolean = false;
constructor(public authService: Authentication) {
this.isAuthenticated = this.authService.isAuthenticated'
}
}
主頁.html
...
<div *ngIf="isAuthenticated">Authentication view</div>
<div *ngIf="!isAuthenticated">Unauthentication view</div>
...
根據上面的當前流程,綁定運行良好,但不是實時的。
那么最好的方法是什么:
1- 在 Authentication 服務中創建一個 observable 以便在組件內部訂閱它。
2- 使用以下方式綁定:
...
<div *ngIf="authService.isAuthenticated">Authentication view</div>
<div *ngIf="!authService.isAuthenticated">Unauthentication view</div>
...
第二種方法效果很好,但我不知道這是否是最佳實踐。
謝謝。
我建議使用BehaviorSubject
。 它是一個Observable
,所以你可以訂閱它,但你也可以通過調用behaviorSubject.next(newValue)
來控制它何時發出新值。 創建 BehaviorSubject 時,您必須將初始值傳遞給它。 在你的情況下,它是false
。
@Injectable()
export class Authentication {
isAuthenticated = new BehaviorSubject<boolean>(false);
login() {
localStorage.setItem('access_token', 'true');
this.isAuthenticated.next(true);
}
}
——
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
private isAuthenticated:boolean;
constructor(public authService: Authentication) {
this.authService.isAuthenticated
.subscribe(isAuthenticated => this.isAuthenticated = isAuthenticated)
}
}
或者您可以使用 Async Pipe 在 html 中訂閱
export class HomePage {
private isAuthenticated: BehaviorSubject<boolean>;
constructor(public authService: Authentication) {
this.isAuthenticated = this.authService.isAuthenticated;
}
}
——
<div *ngIf="isAuthenticated | async">Authentication view</div>
<div *ngIf="!(isAuthenticated | async)">Unauthentication view</div>
與常規的 Observable 不同,當您在 BehaviorSubject 上調用 subscribe 時,您作為參數傳遞給 subscribe 的函數將立即執行。 這是因為 BehaviorSubject 總是有一個值。 您可以使用this.authService.isAuthenticated.value
訪問它,但它在這里不是很有用。
我從你的標簽中假設你正在使用 Ionic 框架? 這可以使用事件來完成嗎?
// first page (publish an event when a user is created)
constructor(public events: Events) {}
createUser(user) {
console.log('User created!')
this.events.publish('user:created', user, Date.now());
}
// second page (listen for the user created event after function is called)
constructor(public events: Events) {
events.subscribe('user:created', (user, time) => {
// user and time are the same arguments passed in `events.publish(user, time)`
console.log('Welcome', user, 'at', time);
});
}
示例代碼取自: https : //ionicframework.com/docs/v3/api/util/Events/
使用 RXJS。 使用 BehaviourSubjects,您可以在注入服務並具有初始狀態的多個組件中推送狀態並訂閱狀態更改。 在定義 BehaviourSubject 時,您還必須定義一個起始值,此處為 false。 你所要做的就是在 BehaviourSubject 上調用.next(true)
來推送狀態,如下所示:
...
@Injectable()
export class Authentication {
private _isAuthenticated: BehaviourSubject<boolean> = new BehaviourSubject(false);
public get isAuthenticated(): Observable<boolean> {
return this._isAuthenticated.asObservable();
}
login() {
localStorage.setItem('access_token', 'true');
this._isAuthenticated.next(true);
}
}
在您的服務上使用 get 方法允許您返回一個可觀察對象,而無需公開暴露 BehaviourSubject 上的方法。
然后在您的組件中:
...
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage implements OnInit {
private isAuthenticated:boolean = false;
private readonly _authService: Authentication;
constructor(authService: Authentication) {
this._authService = authService;
}
public ngOnInit(): void {
this._authService.isAuthenticated
.subscribe((isAuthenticated) => this.isAuthenticated = isAuthenticated)
}
}
目前我正在使用這個解決方案:
import { DoCheck } from '@angular/core';
//...
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
private isAuthenticated:boolean = false;
constructor(public authService: Authentication) { }
ngDoCheck() {
if (this.authService.isAuthenticated)) {
//..if authenticated do this
} else {
//..if not do this
}
}
}
即使我不確定這是一個很好的方式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.