我可以在 Angular 中加载模板之前控制 Oninit() 吗?
Can i control about Oninit() before to load template in Angular?
这个问题我花了3天,我需要你的帮助
我的 Angular 项目中有 2 个关于 google 社交登录的问题。
刷新后保持用户登录(我使用 Google OAuth2)
第一次渲染时,我看不到登录按钮:(
我按照这个解决了第一个问题,但是我按照这个link解决了第一个问题,第二个问题仍然困扰着我
我认为我的项目有问题,在模板渲染后 oninit 函数完成。
此代码是我的 component.ts 文件。
export class NavbarComponent implements OnInit {
log : boolean
test : any
googleAuth: any
auth2 : gapi.auth2.GoogleAuth
constructor(
private ref : ChangeDetectorRef,
private http: HttpClient) { }
async ngOnInit() {
gapi.load('auth2', () => {
gapi.auth2.init({
client_id: 'MY_CLIENT_ID',
scope : 'email',
})
.then((data) => {
this.auth2 = data;
this.googleAuth = gapi.auth2.getAuthInstance();
this.log = this.handleAuthChange();
this.googleAuth.isSignedIn.listen(this.handleAuthChange);
})
})
}
signIn = () => {
this.auth2.signIn()
};
signOut = () => {
this.auth2.signOut();
};
handleAuthChange = () => {
return this.googleAuth.isSignedIn.get();
}
我想做一个登录功能,使用onlu一键所以,我写了这样的模板代码。
<nav class="navbar-container">
<a routerLink="/" class="main-icon-brand">
<img src="../../assets/image/icon.png" alt="logo image" id="icon-image">
</a>
<a routerLink="/tutorial" class="each-item">
<span>Tutorial</span>
</a>
<a routerLink="/making" class="each-item">
<span>Making</span>
</a>
<a routerLink="/search" class="each-item">
<span>Search</span>
</a>
<div id="navbar-space"></div>
<div>
<div *ngIf="log === false">
<button (click)="signIn()" mat-icon-button color="warn">
<mat-icon>account_circle</mat-icon>
</button>
</div>
<div *ngIf="log === true">
<button (click)="signOut()" mat-icon-button color="warn">
<mat-icon>face</mat-icon>
</button>
</div>
</div>
</nav>
嗯...我想,这有两个解决方案
- 阻塞渲染模板直到完成 onInit
- 我尝试了 rxjs observable 但是,我的技能水平很低所以它不起作用(
也许,我对 rxjs 的概念有误)
我假设当您说首次呈现时看不到登录按钮时,您的意思是它加载有延迟。
这不是因为 ngOnInit() 运行 出了问题,而是因为您的 ngOnInit 创建了一个承诺,该承诺在其他一些生命周期完成后才会得到解决。 then(...)
子句中的代码仅在承诺已解决后运行。 Google Api 需要时间来执行您要求它执行的操作,因此您必须围绕它编写一些代码以使您的页面顺利加载。
这是一个大问题,但通常有几种方法可以处理等待 API 数据加载的问题。有些就像设计更改一样简单,以使加载看起来更顺畅。我认为有两种解决方案适合您,
重新考虑您在哪里检查他们是否已登录。您可以在应用程序根目录执行此操作,只需将登录状态传递给导航栏,这样您就不会每次加载导航栏时手动检查。这样您就可以更改加载和等待发生的位置。您可以在应用程序加载时访问 API,而不是在加载导航栏时,甚至可以将登录状态存储在您的状态中,以便您可以从应用程序中的任何位置访问它。
这是更快、更脏的解决方案,但您可以隐藏导航栏,直到它具有完全加载所需的所有数据。这个解决方案看起来像这样,
将您的整个导航栏模板包裹在此,
*ngIf="!(navbarLoading$ | async)"
然后在你的组件中,
public navbarLoading$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);
ngOnInit(): void {
gapi.load('auth2', () => {
gapi.auth2.init({
client_id: 'MY_CLIENT_ID',
scope : 'email',
})
.then((data) => {
this.auth2 = data;
this.googleAuth = gapi.auth2.getAuthInstance();
this.log = this.handleAuthChange();
this.googleAuth.isSignedIn.listen(this.handleAuthChange);
this.navbarLoading$.next(false);
})
})
}
这个问题我花了3天,我需要你的帮助
我的 Angular 项目中有 2 个关于 google 社交登录的问题。
刷新后保持用户登录(我使用 Google OAuth2)
第一次渲染时,我看不到登录按钮:(
我按照这个
我认为我的项目有问题,在模板渲染后 oninit 函数完成。
此代码是我的 component.ts 文件。
export class NavbarComponent implements OnInit {
log : boolean
test : any
googleAuth: any
auth2 : gapi.auth2.GoogleAuth
constructor(
private ref : ChangeDetectorRef,
private http: HttpClient) { }
async ngOnInit() {
gapi.load('auth2', () => {
gapi.auth2.init({
client_id: 'MY_CLIENT_ID',
scope : 'email',
})
.then((data) => {
this.auth2 = data;
this.googleAuth = gapi.auth2.getAuthInstance();
this.log = this.handleAuthChange();
this.googleAuth.isSignedIn.listen(this.handleAuthChange);
})
})
}
signIn = () => {
this.auth2.signIn()
};
signOut = () => {
this.auth2.signOut();
};
handleAuthChange = () => {
return this.googleAuth.isSignedIn.get();
}
我想做一个登录功能,使用onlu一键所以,我写了这样的模板代码。
<nav class="navbar-container">
<a routerLink="/" class="main-icon-brand">
<img src="../../assets/image/icon.png" alt="logo image" id="icon-image">
</a>
<a routerLink="/tutorial" class="each-item">
<span>Tutorial</span>
</a>
<a routerLink="/making" class="each-item">
<span>Making</span>
</a>
<a routerLink="/search" class="each-item">
<span>Search</span>
</a>
<div id="navbar-space"></div>
<div>
<div *ngIf="log === false">
<button (click)="signIn()" mat-icon-button color="warn">
<mat-icon>account_circle</mat-icon>
</button>
</div>
<div *ngIf="log === true">
<button (click)="signOut()" mat-icon-button color="warn">
<mat-icon>face</mat-icon>
</button>
</div>
</div>
</nav>
嗯...我想,这有两个解决方案
- 阻塞渲染模板直到完成 onInit
- 我尝试了 rxjs observable 但是,我的技能水平很低所以它不起作用( 也许,我对 rxjs 的概念有误)
我假设当您说首次呈现时看不到登录按钮时,您的意思是它加载有延迟。
这不是因为 ngOnInit() 运行 出了问题,而是因为您的 ngOnInit 创建了一个承诺,该承诺在其他一些生命周期完成后才会得到解决。 then(...)
子句中的代码仅在承诺已解决后运行。 Google Api 需要时间来执行您要求它执行的操作,因此您必须围绕它编写一些代码以使您的页面顺利加载。
这是一个大问题,但通常有几种方法可以处理等待 API 数据加载的问题。有些就像设计更改一样简单,以使加载看起来更顺畅。我认为有两种解决方案适合您,
重新考虑您在哪里检查他们是否已登录。您可以在应用程序根目录执行此操作,只需将登录状态传递给导航栏,这样您就不会每次加载导航栏时手动检查。这样您就可以更改加载和等待发生的位置。您可以在应用程序加载时访问 API,而不是在加载导航栏时,甚至可以将登录状态存储在您的状态中,以便您可以从应用程序中的任何位置访问它。
这是更快、更脏的解决方案,但您可以隐藏导航栏,直到它具有完全加载所需的所有数据。这个解决方案看起来像这样,
将您的整个导航栏模板包裹在此,
*ngIf="!(navbarLoading$ | async)"
然后在你的组件中,
public navbarLoading$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);
ngOnInit(): void {
gapi.load('auth2', () => {
gapi.auth2.init({
client_id: 'MY_CLIENT_ID',
scope : 'email',
})
.then((data) => {
this.auth2 = data;
this.googleAuth = gapi.auth2.getAuthInstance();
this.log = this.handleAuthChange();
this.googleAuth.isSignedIn.listen(this.handleAuthChange);
this.navbarLoading$.next(false);
})
})
}