编程语言
首页 > 编程语言> > javascript – 使用Typescript进行网站和Angular 2的Google登录

javascript – 使用Typescript进行网站和Angular 2的Google登录

作者:互联网

我正在构建一个具有非常标准的RESTful Web服务的站点来处理持久性和复杂的业务逻辑.我正在构建使用此服务的UI使用Angular 2和使用TypeScript编写的组件.

我希望依靠谷歌登录网站,而不是建立我自己的身份验证系统.想法是用户将访问该站点,通过其中提供的框架登录,然后发送生成的ID令牌,托管RESTful服务的服务器可以验证.

在Google登录文档中有instructions for creating the login button via JavaScript,这是因为登录按钮是在Angular模板中动态呈现的.模板的相关部分:

<div class="login-wrapper">
  <p>You need to log in.</p>
  <div id="{{googleLoginButtonId}}"></div>
</div>
<div class="main-application">
  <p>Hello, {{userDisplayName}}!</p>
</div>

和Typescript中的Angular 2组件定义:

import {Component} from "angular2/core";

// Google's login API namespace
declare var gapi:any;

@Component({
    selector: "sous-app",
    templateUrl: "templates/sous-app-template.html"
})
export class SousAppComponent {
  googleLoginButtonId = "google-login-button";
  userAuthToken = null;
  userDisplayName = "empty";

  constructor() {
    console.log(this);
  }

  // Angular hook that allows for interaction with elements inserted by the
  // rendering of a view.
  ngAfterViewInit() {
    // Converts the Google login button stub to an actual button.
    api.signin2.render(
      this.googleLoginButtonId,
      {
        "onSuccess": this.onGoogleLoginSuccess,
        "scope": "profile",
        "theme": "dark"
      });
  }

  // Triggered after a user successfully logs in using the Google external
  // login provider.
  onGoogleLoginSuccess(loggedInUser) {
    this.userAuthToken = loggedInUser.getAuthResponse().id_token;
    this.userDisplayName = loggedInUser.getBasicProfile().getName();
    console.log(this);
  }
}

基本流程如下:

> Angular呈现模板和消息“Hello,empty!”显示.
>触发ngAfterViewInit挂钩并调用gapi.signin2.render(…)方法,将空div转换为Google登录按钮.这可以正常工作,单击该按钮将触发登录过程.
>这也会附加组件的onGoogleLoginSuccess方法,以便在用户登录后实际处理返回的令牌.
> Angular检测到userDisplayName属性已更改并更新页面现在显示“Hello,Craig(或您的名字)!”.

发生的第一个问题是onGoogleLoginSuccess方法.注意构造函数和该方法中的console.log(…)调用.正如所料,构造函数中的那个返回Angular组件.但是,onGoogleLoginSuccess方法中的那个返回JavaScript窗口对象.

因此看起来上下文在跳出到Google的登录逻辑的过程中迷失了所以我的下一步是尝试合并jQuery的$.proxy调用以挂起正确的上下文.所以我通过添加declare var $:any导入jQuery名称空间;到组件的顶部,然后将ngAfterViewInit方法的内容转换为:

// Angular hook that allows for interaction with elements inserted by the
// rendering of a view.
ngAfterViewInit() {
    var loginProxy = $.proxy(this.onGoogleLoginSuccess, this);

    // Converts the Google login button stub to an actual button.
    gapi.signin2.render(
      this.googleLoginButtonId,
      {
        "onSuccess": loginProxy,
        "scope": "profile",
        "theme": "dark"
      });
}

添加之后,两个console.log调用将返回相同的对象,因此属性值现在可以正确更新.第二条日志消息显示具有预期更新属性值的对象.

不幸的是,当发生这种情况时,Angular模板不会更新.在调试时,我偶然发现了一些我认为可以解释发生了什么的事情.我在ngAfterViewInit钩子的末尾添加了以下行:

setTimeout(function() {
  this.googleLoginButtonId = this.googleLoginButtonId },
  5000);

这不应该做任何事情.它只是在钩子结束后等待五秒钟,然后设置一个等于它自己的属性值.然而,随着线路到位“你好,空!”消息变成“你好,克雷格!”页面加载后大约五秒钟.这告诉我,Angular没有注意到onGoogleLoginSuccess方法中的属性值正在发生变化.因此,当其他事情发生时,通知Angular属性值已经改变(例如上面的其他无用的自我赋值),Angular会唤醒并更新所有内容.

显然,这不是一个我想留下的黑客,所以我想知道是否有任何Angular专家可以让我知道?是否有一些电话我应该强迫Angular注意到一些属性已经改变了?

更新2016-02-21以提供解决问题的具体答案的清晰度

我最终需要使用所选答案中提供的两条建议.

首先,完全按照建议,我需要转换onGoogleLoginSuccess方法以使用箭头功能.其次,我需要使用NgZone对象来确保属性更新发生在Angular知道的上下文中.所以最后的方法最终看起来像

onGoogleLoginSuccess = (loggedInUser) => {
    this._zone.run(() => {
        this.userAuthToken = loggedInUser.getAuthResponse().id_token;
        this.userDisplayName = loggedInUser.getBasicProfile().getName();
    });
}

我确实需要导入_zone对象:从“angular2 / core”导入{Component,NgZone};

我还需要通过类的构造函数在答案中建议注入它:constructor(private _zone:NgZone){}

解决方法:

对于您的第一个问题解决方案是使用arrow function,这将保留以下内容:

  onGoogleLoginSuccess = (loggedInUser) => {
    this.userAuthToken = loggedInUser.getAuthResponse().id_token;
    this.userDisplayName = loggedInUser.getBasicProfile().getName();
    console.log(this);
  }

第二个问题正在发生,因为第三方脚本在Angular的上下文之外运行. Angular使用区域,所以当你运行某些东西时,例如setTimeout(),它会被猴子修补以在区域中运行,Angular会得到通知.您可以在区域中运行jQuery,如下所示:

  constructor(private zone: NgZone) {
    this.zone.run(() => {
      $.proxy(this.onGoogleLoginSuccess, this);
    });
  }

关于该区域有很多问题/答案,如果您想了解更多,那么我的解释会更好,但如果您使用箭头功能,它不应该是您的示例的问题.

标签:javascript,angular,typescript,google-login
来源: https://codeday.me/bug/20190925/1817610.html