奥瑞利亚谷歌登录按钮

3

我刚开始使用Aurelia,但在Google登录方面遇到了问题。看起来我可以创建自己的Google按钮,但如果可能的话,我更愿意通过下列代码使其正常工作:

<script src="https://apis.google.com/js/platform.js" async defer></script>
...
<body aurelia-app="src/main">
...
<span id="googleButtonPlaceholder" class="g-signin2" data-onsuccess="onSignIn"></span>

我在我的Aurelia类中设置了功能,但我不知道如何调用它。我已经尝试使用${onSignIn()},它只是在加载时调用函数,${onSignIn}onSignIn()onSignIndata-onsuccess.bind="onSignin()",但没有任何效果。有没有办法将Aurelia函数传递给Google的data-onsuccess属性?
需要注意的是,我正在从先前可以工作的Angular 1.5.8切换。

传递函数引用可能会让你感到困扰,因为它不是全局定义的函数,所以 Google 不知道如何定位它。 - PW Kad
那就是问题的一部分。谷歌在模板加载之前加载,因此它尚未定义。感谢您的评论。 - Galastun
4个回答

3
这是一个例子:https://gist.run?id=5da90f48b43b9c5867c8d2ace0f6371f

app.html

<template>
  <require from="google-signin-button"></require>

  <google-signin-button success.call="signinSuccess(googleUser)"
                        error.call="signinError(error)">
  </google-signin-button>

  <h1>${message}</h1>
</template>

app.js

export class App {
  message = 'Not signed in.';

  signinSuccess(googleUser) {
    const name = googleUser.getBasicProfile().getName();
    this.message = `Signed in: ${name}`;
  }

  signinError(error) {
    this.message = `Error: ${error}`;
  }
}

google-signin-button.js

import {inject, noView, bindable} from 'aurelia-framework';

const googleSigninClientID = '927519533400-mfupo3lq9cjd67fmmvtth7lg7d8l50q9.apps.googleusercontent.com';

function preparePlatform() {
  // https://developers.google.com/identity/sign-in/web/build-button

  // The name of the global function the platform API will call when
  // it's ready.
  const platformCallbackName = 'setGooglePlatformReady';

  // An "API ready" promise that will be resolved when the platform API 
  // is ready.
  const ready = new Promise(  
    resolve => window[platformCallbackName] = resolve);

  // Inject the client id meta tag
  const meta = document.createElement('meta');
  meta.name = 'google-signin-client_id';
  meta.content = googleSigninClientID;
  document.head.appendChild(meta);

  // Inject an async script element to load the google platform API.
  // Notice the callback name is passed as an argument on the query string.
  const script = document.createElement('script');  
  script.src = `https://apis.google.com/js/platform.js?onload=${platformCallbackName}`;  
  script.async = true;  
  script.defer = true;  
  document.head.appendChild(script);

  return ready;
}

const platformReady = preparePlatform();

@noView()
@inject(Element)
export class GoogleSigninButton {  
  @bindable success = googleUser => { };
  @bindable error = error => { };
  @bindable scope = 'profile email';
  @bindable theme = 'dark';
  @bindable width = 240;
  @bindable height = 50;

  constructor(element) {
    this.element = element;
  }

  attached() {
    platformReady.then(this.renderButton);
  }

  renderButton = () => {
    gapi.signin2.render(this.element, {
      scope: this.scope,
      width: this.width,
      height: this.height,
      longtitle: true,
      theme: this.theme,
      onsuccess: googleUser => {
        console.info(googleUser);
        this.success({ googleUser });
      },
      onfailure: error => {
        console.error(error);
        this.failure({ error });
      }
    });
  }
}

谢谢你的帮助!那是一个有效的好解决方案!我找到了另一种方法,使用稍微不同的方法来完成它,但仍然不需要我自己制作Google按钮。最终我采用了不同的方法,但你的答案也是完全可以接受的。 - Galastun
太棒了的例子! - Hardycore

1

@JeremyDanyow给出了一个很好的答案,但是在我睡觉后,我又读了一些关于Aurelia的内容,想到了一个解决方案,在看到他的答案之前可以尝试一下,所以我想分享一个备选方法给那些感兴趣的人。

index.html

<main aurelia-app="src/main">
</main>

<script src="https://apis.google.com/js/platform.js" async defer></script>

app.html

<template>
    <span id="my-signin2"></span>
    <!-- other stuff -->
</template>

app.js

attached() {
   this.render();
}

render() {
   gapi.signin2.render('my-signin2', {
      'scope': 'profile email',
      'theme': 'dark',
      'onsuccess': this.onSuccess,
      'onfailure': this.onFailure
   });
}

onSuccess(googleuser) {
  let gUser = googleuser.getBasicProfile(),
      id_token = googleuser.getAuthResponse().id_token;
}

onFailure(error) {
   console.log(error);
}

这种方法与谷歌网站上展示的略有不同,他们要求您提供一个onload函数来渲染按钮。相反,我在模板中创建按钮,然后一旦模板加载完成,就会调用attached(),这将调用我本来想让platform.js调用的函数onload

1
如果不使用onload回调函数,那么当组件的附加方法被调用时,Google平台API脚本的异步加载可能尚未完成。虽然这种情况不太可能发生,但我相信Google的API脚本加载速度非常快。 - Jeremy Danyow
你说得对。这正是我担心的事情,所以你的答案可能是更好的方法。我考虑过的一个问题是尝试将Google脚本放在页面顶部并使其同步加载。 - Galastun
更简单了!谢谢! - Hardycore

0
尝试使用 data-onsuccess.call="onSignIn()"

你是正确的,应该使用 call。我实际上尝试过,但在我的帖子中错误地放了 bind。感谢您的评论。 - Galastun

0

在跟随@JeremyDanyow的示例走了几个弯路后,我想出了这个方法

对于简单的用法,它可以正常工作,但需要帮助...

  1. 当有另一个使用Google登录的窗口打开时,iframe中Google添加的某些内容会出现错误加载(这似乎不会破坏它)

  2. 监听器最多只能工作几次登录/注销

希望有人能改进这个方法。

google-signin-button.js

import { inject, noView, bindable } from 'aurelia-framework';

import { LogManager } from 'aurelia-framework';
const Console = LogManager.getLogger('google-signin-button');

// Integrating Google Sign-In into your web app
// https://developers.google.com/identity/sign-in/web/reference
// https://console.developers.google.com/apis/credentials

// inspiration: https://developers.google.com/identity/sign-in/web/build-button
function preparePlatform(): Promise<Function> {
  // Inject an async script element to load the google platform API.
  const script = document.createElement('script');
  script.src = `https://apis.google.com/js/platform.js?onload=gapi_ready`;
  script.async = true;
  script.defer = true;
  document.head.appendChild(script);
  // return a promise that will resolve with the onload callback
  return new Promise(resolve => window['gapi_ready'] = resolve);
}

@noView
@inject(Element)
export class GoogleSigninButton {

  @bindable authenticated = (signedIn: Boolean) => { };
  @bindable authorized = (GoogleUser: any) => { };

  @bindable scope = 'profile email';
  @bindable clientId = 'none';

  @bindable theme = 'dark';
  @bindable width = 240;
  @bindable height = 50;

  public element: Element;

  constructor(element) {
    this.element = element;
  }

  public wasAuthenticated: Boolean;
  sendAuthenticated(signedIn: Boolean) {
    if (signedIn !== this.wasAuthenticated) {
      this.authenticated(signedIn);
      this.wasAuthenticated = signedIn;
    }
  }

  public wasAuthorized: any;
  sendAuthorized(googleUser: any) {
    if (googleUser !== this.wasAuthorized) {
      this.authorized(googleUser);
      this.wasAuthorized = googleUser;
      this.sendAuthenticated(true);
    }
  }

  attached() {
    // inject the script tag
    preparePlatform()
      .then(() => {
        // load the auth lib
        // Console.debug('gapi created, loading auth2');
        window['gapi'].load('auth2', () => {
          // init the auth lib
          // Console.debug('gapi.auth2 loaded, intializing with clientId:', this.clientId);
          window['gapi'].auth2.init({
            client_id: this.clientId
          })
            .then(
              (googleAuth: any) => {
                // Console.debug('gapi.auth2 intialized');
                // listen for user signed in/out
                googleAuth.isSignedIn.listen((signedIn: Boolean) => {
                  // Console.debug('googleAuth.isSignedIn.listener', signedIn);
                  this.sendAuthenticated(signedIn);
                });
                // listen for who signed in
                googleAuth.currentUser.listen((googleUser: any) => {
                  // Console.debug('googleAuth.currentUser.listener', googleUser);
                  this.sendAuthorized(googleUser);
                });
                // draw the button
                window['gapi'].signin2.render(this.element, {
                  scope: this.scope,
                  width: this.width,
                  height: this.height,
                  longtitle: true,
                  theme: this.theme,
                  onsuccess: (googleUser: any) => {
                    // Console.debug('gapi.signin2.render success', googleUser);
                    this.sendAuthorized(googleUser);
                  },
                  // drawing button failure
                  onfailure: (error: any) => {
                    Console.error('gapi.signin2.render failure', error);
                  }
                });
              },
              // intialization error
              (errObj: any) => {
                Console.error('gapi.auth2.init -> errObj', errObj);
              }
            );
        });
      });
  }
}

some-usage.js

import environment from '../environment';

import { LogManager } from 'aurelia-framework';
const Console = LogManager.getLogger('Login');

import { inject } from 'aurelia-framework';
import { AuthService } from 'aurelia-authentication';
import { EventAggregator } from 'aurelia-event-aggregator';

import './login.scss';

@inject(AuthService, EventAggregator)
export class Login {

  public authService: AuthService;
  public eventAggregator: EventAggregator;

  public googleSigninClientID: string = 'none';

  constructor(authService: AuthService, eventAggregator: EventAggregator) {
    this.eventAggregator = eventAggregator;
    this.authService = authService;

    this.googleSigninClientID = environment.googleSigninClientID;
  };

  isAuthenticated(signedIn: Boolean) {
    Console.warn('isAuthenticated', signedIn);
  }

  isAuthorized(googleUser: any) {
    Console.warn('isAuthorized', googleUser);
  }

}

some-usage.html

<template>
  <require from="../resources/elements/google-signin-button"></require>
  <section>
    <div class="container-fluid">
      <center>
        <google-signin-button client-id.bind="googleSigninClientID" authenticated.bind="isAuthenticated" authorized.bind="isAuthorized"> </google-signin-button>
      </center>
    </div>
  </section>
</template>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接