2017-01-30 4 views
0

Immer noch versuchen, eine Antwort auf Aurelia JS - Making a synchronous HTTP request, to change data before page load? zu finden - so habe ich es auf die folgende Frage reduziert.Aurelia - Wie ändere ich gebundene Variablen, so ändert sich die GUI?

Lassen Sie uns sagen, dass wir mit Kontaktmanager Tutorial arbeiten:

..., deren Code auch auf https://gist.run/?id=c73b047c8184c052b4c61c69febb33d8 kopiert ...

Nun, das ist, wie ich gelesen der code: in contact-list.js, in der constructor() von ContactList Klasse, wir haben:

export class ContactList { 
    static inject = [WebAPI, EventAggregator]; 

    constructor(api, ea){ 
    this.api = api; 
    this.contacts = []; 
... 

... so wird im Konstruktor this.contacts der ContactList Klasse zu einem leeren Array initialisiert.

Dann wurde in der gleichen ContactList Klasse gibt es eine created() Methode:

created(){ 
    this.api.getContactList().then(contacts => this.contacts = contacts); 
} 

Dies ruft die Kontaktliste, wie in web-api.js definiert und weist sie der Klasse ContactList Eigenschaft this.contacts, die vorher leer war .

schließlich in contact-list.html haben wir:

<li repeat.for="contact of contacts" class="list-group-item ${contact.id === $parent.selectedId ? 'active' : ''}"> 
    ... 

... die offenbar iteriert durch this.contacts der Klasse ContactList und macht <li> (und andere) Elemente in dem HTML-GUI auf dieser Grundlage.

So, wie ich das verstehe, ist die Idee, dass, wenn die this.contacts Eigenschaft der ContactList Klasse geändert wird, dann wird die <li repeat.for="contact of contacts" ... wieder ausgeführt werden soll, und zeigt eine aktualisierte GUI in Übereinstimmung mit den Daten.

Allerdings kann ich das nicht demonstrieren. Die einfachste, dachte ich, wäre eine Funktion zu haben, ein paar Sekunden ausgeführt werden, nachdem die created() Methode von ContactList ausgeführt wurde, so habe ich versucht, setTimeout dafür zu verwenden:

created(){ 
    this.api.getContactList().then(contacts => this.contacts = contacts); 
    setTimeout(this.changeContactList, 3000); // call changeContactList() function after 3 seconds 
} 

... und ich habe eine hinzugefügt changeContactList Methode, die dies:

changeContactList() { 
    this.contacts = [ { 
     id:13, 
     firstName:'Bob', 
     lastName:'Rock', 
     email:'[email protected]', 
     phoneNumber:'888-7303' 
    } 
    ]; 
    alert("changeContactList done " + this.contacts.length); 
    } 

Also, es ist nur eine einfache Zuordnung von this.contacts der ContactList Klasse auf ein neues Datenfeld.

Also, dafür bekomme ich tatsächlich nach einigen Sekunden ein Alarmfenster; es heißt "changeContactList done 1", was bedeutet, dass das this.contacts Array tatsächlich auf die neuen Daten geändert wurde - außer, dass es überhaupt keine Änderungen in der GUI gibt ?!

Also, was mache ich falsch? Soll ich eine zusätzliche Funktion aufrufen, um den aktualisierten Status rendern zu lassen? Aber wenn ich eine zusätzliche Funktion aufrufen muss, was ist dann der bindende Punkt? Mit anderen Worten - was muss ich tun, um die GUI zu aktualisieren und den neu geänderten Zustand des this.contacts Arrays anzuzeigen?

Antwort

0

Ok, gefunden, was das Problem ist - das Problem mit dem Code oben, dass die Bedeutung von this ändert sich, wenn Sie setTimeout verwenden - in diesem Fall this ein Verweis auf Window wird, nicht auf eine Instanz der definierenden Klasse! (Der Rest der Bindung funktioniert anscheinend, wie ich es vorher verstanden hatte)

In diesem Sinne habe ich endlich die GUI die aktualisierte Datenfeld mit den folgenden Änderungen in contact-list.js zeigen:

created(){ 
    this.api.getContactList().then(contacts => { this.contacts = contacts ; 
     //setTimeout(this.changeContactList, 1000); // timeout delay ok, but 'this' becomes Window 
     //setTimeout(this.changeContactList(this), 1000); // timeout delay not honored here 
     //setTimeout(function() {console.log(this); this.changeContactList(this);}, 1000); // "this.changeContactList is not a function"; 'this' is Window 

     // works OK: 
     //var copythis = this; // make a copy of 'this', since 'this' looses meaning in the setTimeout 
     //setTimeout(function() {console.log(copythis); copythis.changeContactList();}, 1000); // 
    }); 
    console.log(this.contacts); // is empty [] here - Promise unresolved yet 

    // also works OK: 
    var copythis = this; // make a copy of 'this', since 'this' looses meaning in the setTimeout 
    setTimeout(function() {console.log(copythis); copythis.changeContactList();}, 2000); // 
    } 

    changeContactList() { 
    //this.contacts = [ { 
    // id:13, 
    // firstName:'Bob', 
    // lastName:'Rock', 
    // email:'[email protected]', 
    // phoneNumber:'888-7303' 
    //} 
    //]; 
    // "this" is Window here, if called from setTimeout(this.changeContactList, 
    // but if called as setTimeout(this.changeContactList(this), then "this" is ContactList! - but then timeout delay is not honoured 

    console.log(this); 
    console.log(this.contacts); 
    this.contacts.push({ 
     id:13, 
     firstName:'Bob', 
     lastName:'Rock', 
     email:'[email protected]', 
     phoneNumber:'888-7303' 
    }); 
    alert("changeContactList done " + this.contacts.length); 
    } 
Verwandte Themen