Angular 尽管模型中的变量已更改,但视图未更新
Angular view not updating despite variables changed in model
我正在使用 Gooogle OAuth 制作一个 youtube 播放列表项目,我在处理身份验证过程时遇到了一个小问题,变量 isAuthorized
是我存储用户登录状态的地方,我可以在在用户登录后,它在控制台中更改为 true,但在 View 部分中它仍然是 false。我想知道我究竟是如何解决这个问题的?
下面是我的模型部分的代码
GoogleAuth: any;
user: any;
isAuthorized = false;
ngOnInit(): void {
// Load auth2 library
gapi.load("client:auth2", this.initClient);
}
loadClient = () => {
gapi.client.setApiKey(this.API_KEY);
return gapi.client
// same as "https://www.googleapis.com/discovery/v1/apis/youtube/v3/rest"
.load("youtube", "v3")
.then(
() => {
console.log("GAPI client loaded for API");
},
function (err) {
console.error("Error loading GAPI client for API", err);
}
);
}
// Init API client library and set up sign in listeners
initClient = () => {
gapi.client
.init({
discoveryDocs: this.DISCOVERY_DOCS,
clientId: this.CLIENT_ID,
scope: this.SCOPES,
})
.then(() => {
this.GoogleAuth = gapi.auth2.getAuthInstance();
// Listen for sign-in state changes.
this.GoogleAuth.isSignedIn.listen(this.handleSigninStatus);
// Handle initial sign-in state. (Determine if user is already signed in.)
this.handleSigninStatus();
this.loadClient()
});
}
handleSigninStatus = () => {
this.user = this.GoogleAuth.currentUser.get();
this.isAuthorized = this.user.hasGrantedScopes(this.SCOPES);
if (this.isAuthorized) {
this.loadClient()
// this.getChannelInfo() //display playlist data
} else {
//do nothing
}
}
// Handle login
handleAuthClick = () => {
this.GoogleAuth.signIn({ scope: this.SCOPES })
.then(() => {
console.log("Sign-in successful");
// this.isLoggedIn = true
this.getChannelInfo()
},
(err: any) => { console.error("Error signing in", { err }) });
}
// Handle logout
handleSignoutClick = () => {
this.GoogleAuth.signOut();
this.GoogleAuth.disconnect();
// gapi.auth2.getAuthInstance().signOut().then(() => { this.googleUser = null });
}
这是我的 HTML,也就是视图部分:
<mat-toolbar>
<a href="/">My Application {{isAuthorized}}</a>
<ng-template [ngIf]="isAuthorized" [ngIfElse]="loggedOut">
<button mat-raised-button color="warn" id="signout-button" (click)="handleSignoutClick()">Log Out</button>
</ng-template>
<ng-template #loggedOut>
<button mat-raised-button color="warn" id="authorize-button" (click)="handleAuthClick()">Log In</button>
</ng-template>
</mat-toolbar>
因为 this.GoogleAuth
事件在 angular 的 scope/zone 之外运行,您需要将其回调带入 angular 区域。这样 angular 的生命周期事件将适当地处理数据的变化。
用 ngZone's run 函数包装您的事件处理函数。每次通过不属于 angular scope/zone:
的事件修改 angular 监视变量时,建议这样做
constructor(private ngZone: NgZone ...
...
initClient = () => {
gapi.client
.init({
discoveryDocs: this.DISCOVERY_DOCS,
clientId: this.CLIENT_ID,
scope: this.SCOPES,
})
.then(() => {
this.ngZone.run(() => { // <-- here
this.GoogleAuth = gapi.auth2.getAuthInstance();
// Listen for sign-in state changes.
this.GoogleAuth.isSignedIn.listen(this.handleSigninStatus);
// Handle initial sign-in state. (Determine if user is already signed in.)
this.handleSigninStatus();
this.loadClient()
});
});
}
handleSigninStatus = () => {
this.ngZone.run(() => { // <-- here
this.user = this.GoogleAuth.currentUser.get();
this.isAuthorized = this.user.hasGrantedScopes(this.SCOPES);
if (this.isAuthorized) {
this.loadClient()
// this.getChannelInfo() //display playlist data
} else {
//do nothing
}
});
}
将模型修改带入 angular 的 scope/zone 的最简单方法是像上面这样用 ngZone 调用包装它们。
我正在使用 Gooogle OAuth 制作一个 youtube 播放列表项目,我在处理身份验证过程时遇到了一个小问题,变量 isAuthorized
是我存储用户登录状态的地方,我可以在在用户登录后,它在控制台中更改为 true,但在 View 部分中它仍然是 false。我想知道我究竟是如何解决这个问题的?
下面是我的模型部分的代码
GoogleAuth: any;
user: any;
isAuthorized = false;
ngOnInit(): void {
// Load auth2 library
gapi.load("client:auth2", this.initClient);
}
loadClient = () => {
gapi.client.setApiKey(this.API_KEY);
return gapi.client
// same as "https://www.googleapis.com/discovery/v1/apis/youtube/v3/rest"
.load("youtube", "v3")
.then(
() => {
console.log("GAPI client loaded for API");
},
function (err) {
console.error("Error loading GAPI client for API", err);
}
);
}
// Init API client library and set up sign in listeners
initClient = () => {
gapi.client
.init({
discoveryDocs: this.DISCOVERY_DOCS,
clientId: this.CLIENT_ID,
scope: this.SCOPES,
})
.then(() => {
this.GoogleAuth = gapi.auth2.getAuthInstance();
// Listen for sign-in state changes.
this.GoogleAuth.isSignedIn.listen(this.handleSigninStatus);
// Handle initial sign-in state. (Determine if user is already signed in.)
this.handleSigninStatus();
this.loadClient()
});
}
handleSigninStatus = () => {
this.user = this.GoogleAuth.currentUser.get();
this.isAuthorized = this.user.hasGrantedScopes(this.SCOPES);
if (this.isAuthorized) {
this.loadClient()
// this.getChannelInfo() //display playlist data
} else {
//do nothing
}
}
// Handle login
handleAuthClick = () => {
this.GoogleAuth.signIn({ scope: this.SCOPES })
.then(() => {
console.log("Sign-in successful");
// this.isLoggedIn = true
this.getChannelInfo()
},
(err: any) => { console.error("Error signing in", { err }) });
}
// Handle logout
handleSignoutClick = () => {
this.GoogleAuth.signOut();
this.GoogleAuth.disconnect();
// gapi.auth2.getAuthInstance().signOut().then(() => { this.googleUser = null });
}
这是我的 HTML,也就是视图部分:
<mat-toolbar>
<a href="/">My Application {{isAuthorized}}</a>
<ng-template [ngIf]="isAuthorized" [ngIfElse]="loggedOut">
<button mat-raised-button color="warn" id="signout-button" (click)="handleSignoutClick()">Log Out</button>
</ng-template>
<ng-template #loggedOut>
<button mat-raised-button color="warn" id="authorize-button" (click)="handleAuthClick()">Log In</button>
</ng-template>
</mat-toolbar>
因为 this.GoogleAuth
事件在 angular 的 scope/zone 之外运行,您需要将其回调带入 angular 区域。这样 angular 的生命周期事件将适当地处理数据的变化。
用 ngZone's run 函数包装您的事件处理函数。每次通过不属于 angular scope/zone:
的事件修改 angular 监视变量时,建议这样做constructor(private ngZone: NgZone ...
...
initClient = () => {
gapi.client
.init({
discoveryDocs: this.DISCOVERY_DOCS,
clientId: this.CLIENT_ID,
scope: this.SCOPES,
})
.then(() => {
this.ngZone.run(() => { // <-- here
this.GoogleAuth = gapi.auth2.getAuthInstance();
// Listen for sign-in state changes.
this.GoogleAuth.isSignedIn.listen(this.handleSigninStatus);
// Handle initial sign-in state. (Determine if user is already signed in.)
this.handleSigninStatus();
this.loadClient()
});
});
}
handleSigninStatus = () => {
this.ngZone.run(() => { // <-- here
this.user = this.GoogleAuth.currentUser.get();
this.isAuthorized = this.user.hasGrantedScopes(this.SCOPES);
if (this.isAuthorized) {
this.loadClient()
// this.getChannelInfo() //display playlist data
} else {
//do nothing
}
});
}
将模型修改带入 angular 的 scope/zone 的最简单方法是像上面这样用 ngZone 调用包装它们。