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 调用包装它们。