Angular6:外部js库和绑定问题

Angular 6 : external js library and binding problem

在我的应用程序中我加载了一个外部库"braintree.js"...一切正常,但有一个我无法理解的奇怪行为。

在我的模板中,根据 var (regStep) 的值加载了一个 div 块:当我调用外部库时,即使 regStep 的值发生变化,模板也不会显示变化,如果我评论了对外部库的调用并更改了 regStep 的值,模板相应地更改。

我没有复制所有代码,但我保证声明了所有需要的变量。

我是Angular的新手,也许我失去了一些东西,但我真的不明白问题在哪里。

这些是涉及的文件:

component.html

<div *ngIf="regservice.regStep == 1">
   <form (ngSubmit)="regservice.savePay();
   ...tags...
   </form>
</div>
<div *ngIf="regservice.regStep == 2">
   ...tags...
</div>

regservice.ts

declare var braintree: any;

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { HttpClient } from '@angular/common/http';

@Injectable({
   providedIn: 'root'
})

export class RegisterService {

  constructor(public router: Router, private http: HttpClient) {}
  public regStep = 1;

public savePay() : void {

let self = this;

let client = new braintree.api.Client({clientToken: this.bt_token});

client.tokenizeCard({
  number: '',
  expirationDate: '',
  cvv : ''
}, function (err, nonce) {
  if (nonce) {
    console.log(nonce); 
    self.addPayment(nonce);
  }
});
//this.addPayment('fake-valid-nonce');
//If I uncomment the above line and comment all the others everything works perfectly
}

private addPayment(nonce) : void {  

 this.http.post(this.apiUrl+'/bt-add-payment-method/',
{
    payment_method_nonce: nonce,
    billing_address_id: this.business.braintree_customer.id,
    make_default: true

},
{
  headers:{
    'Content-Type': 'application/json',
    'Authorization': 'Bearer ' + this.token['access_token']
  }}).subscribe( {
      next : response => { console.log('RESPONSE ADD PYMNT : ',response); },
      error: err => {this.handleErrors(err); },
      complete: () => { this.forward(); },
    }); 
 }

 private forward() {
  switch (this.regStep) {
     case 1 : {
        this.regStep_value = 'Step 2 of 5';
        this.regStep++;             
    }
    break;
  }
}

更新

甚至使用:

client.tokenizeCard({
  number: '',
  expirationDate: '',
  cvv : ''
}, (err, nonce) => {
    console.log(nonce); 
    this.addPayment(nonce);  
});

问题仍然存在。模板保持阻塞到 STEP == 1 块。

如果我不调用 new braintree 和相关代码,一切正常。

在这两种情况下,我都可以看到 console.log RESPONSE ADD PYMNT,因此在这两种情况下都调用了 AddPayment 函数;在这两种情况下也调用前向函数。

在这两种情况下,我都可以看到 regStep 是 2,但是

  1. 如果我调用了 braintree,模板会保持之前的状态。

  2. 如果我没有调用 braintree,模板会随着 regStep 的变化而变化。

如果您想在回调中使用组件 variables/methods,更好的方法是使用 lambda (=>) 函数,而不是使用文字或匿名函数。在您的情况下,您可以使用以下内容:

(err, nonce) => {   
   if (nonce) {
       console.log(nonce); 
       this.addPayment(nonce);   
    }
}

问题与退出 Angular 区域的异步函数有关。

这将解决问题:

client.tokenizeCard({
  number: '',
  expirationDate: '',
  cvv : ''
}, (err, nonce) => {
  this.zone.run(() => { //<=== added
    console.log(nonce); 
    this.addPayment(nonce);  
  })
});

逻辑上你必须导入 NgZone

import { NgZone } from '@angular/core';

export class RegisterService {

  constructor(private zone:NgZone ) {}
}