当前位置: 动力学知识库 > 问答 > 编程问答 >

javascript - Aurelia - how to change bound variables, so the GUI changes?

问题描述:

Still trying to find an answer to Aurelia JS - Making a synchronous HTTP request, to change data before page load? - so I've reduced it to the following question.

Let's say we work with contact manager tutorial:

  • http://aurelia.io/hub.html#/doc/article/aurelia/framework/latest/contact-manager-tutorial/1

... whose code is also copied on https://gist.run/?id=c73b047c8184c052b4c61c69febb33d8 ...

Now, this is how I read the code: in contact-list.js, in the constructor() of ContactList class, we have:

export class ContactList {

static inject = [WebAPI, EventAggregator];

constructor(api, ea){

this.api = api;

this.contacts = [];

...

... so in the constructor, this.contacts of the ContactList class is initialized to an empty array.

Then, in the same ContactList class, there is a created() method:

created(){

this.api.getContactList().then(contacts => this.contacts = contacts);

}

This retrieves the contact list as defined in web-api.js, and it assigns it to the class ContactList property this.contacts, which was previously empty.

Finally, in contact-list.html, we have:

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

...

... which apparently iterates through this.contacts of the class ContactList, and makes <li> (and other) elements in the HTML GUI based on that.

So, as I understand this, the idea is that whenever the this.contacts property of the ContactList class changed, then the <li repeat.for="contact of contacts" ... should execute again, and show an updated GUI in accordance with the data.

However, I cannot get to demonstrate this. The easiest, I thought, would be to have a function execute a few seconds after the created() method of ContactList has run, so I tried to use setTimeout for that:

created(){

this.api.getContactList().then(contacts => this.contacts = contacts);

setTimeout(this.changeContactList, 3000); // call changeContactList() function after 3 seconds

}

... and I've added a changeContactList method which is this:

 changeContactList() {

this.contacts = [ {

id:13,

firstName:'Bob',

lastName:'Rock',

email:'[email protected]',

phoneNumber:'888-7303'

}

];

alert("changeContactList done " + this.contacts.length);

}

So, it is just a simple assignment of this.contacts of the ContactList class to a new data array.

So, for this, I do indeed get an alert window after some seconds; it does say "changeContactList done 1" meaning that the this.contacts array has indeed been changed to the new data - except, there are no changes whatsoever in the GUI?!

So what am I doing wrong? Am I supposed to call an additional function to have the updated state render? But if I have to call an additional function, what is the point of binding, then? In other words - what do I have to do, to get the GUI to update and show the newly changed state of the this.contacts array?

网友答案:

Ok, found what the problem is - the problem with the code above is that the meaning of this changes when you use setTimeout - in that case, this becomes a reference to Window, not to an instance of the defining class! (the rest of the binding apparently works as I had understood it previously)

With that in mind, I finally got the GUI to show the updated data array with the following changes in contact-list.js:

  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);
  }
分享给朋友:
您可能感兴趣的文章:
随机阅读: