Aurelia-通过注入访问更新的类属性? [英] Aurelia - accessing updated class properties from injection?
问题描述
我仍在寻找 https://gist.run/?id=90d98563621fe49c1dde6b4f2fc6961d .
I'm still trying to find an answer to Aurelia JS - Making a synchronous HTTP request, to change data before page load? - so I tried the following in the code example for that question, https://gist.run/?id=90d98563621fe49c1dde6b4f2fc6961d .
根据 Aurelia-如何更改绑定变量,因此GUI也要更改?,我知道我可以更改作为HTML绑定源的类变量,并且HTML/GUI应该更新.因此,我正在尝试上述要点中的类似内容-具体来说,我正在尝试更改ContactList
类(在contact-list.js
中)的contacts
数组属性.
As per Aurelia - how to change bound variables, so the GUI changes?, I am aware that I can change a class variable that is a source of a HTML binding, and the HTML/GUI should update. So I'm trying something similar in the gist above - specifically, I am trying to change the contacts
array property of the ContactList
class (in contact-list.js
).
以下是app-clist.js
中的相关更改:
import {WebAPI} from './web-api';
import {HttpClient} from 'aurelia-http-client';
import {ContactList} from './contact-list';
import {Container} from 'aurelia-dependency-injection';
// for multiline string, use backticks `` - ES6 template literals.
let phpcode = `
<?php
$outarr = array();
$tObj = new StdClass();
$tObj->{'id'} = '1';
$tObj->{'firstName'} = 'Bob';
$tObj->{'lastName'} = 'Glass';
$tObj->{'email'} = 'bob@glass.com';
$tObj->{'phoneNumber'} = '243-6593';
array_push($outarr, $tObj);
$tObj = new StdClass();
$tObj->{'id'} = '2';
$tObj->{'firstName'} = 'Chad';
$tObj->{'lastName'} = 'Connor';
$tObj->{'email'} = 'chad@connor.com';
$tObj->{'phoneNumber'} = '839-2946';
array_push($outarr, $tObj);
echo json_encode($outarr);
?>
`;
export class AppClist { // in gist example is wrong, still called App
static inject() { return [WebAPI, HttpClient, ContactList]; }
constructor(api, http, conlist){
this.api = api;
this.http = http;
this.conlist = conlist;
var phpcodesl = phpcode.replace(/(?:\r\n|\r|\n)/g, ' ');
var encphpcode = encodeURIComponent(phpcodesl); // urlencode
//alert(encphpcode);
// NOTE: gist.run due https will not allow loading from http
//this.http.post("https://phpfiddle.org/api/run/code/json", "code="+encphpcode )
//.then(response => {alert(response.response); console.log(response);}) // does not work
// this does work:
console.log("a1", this.conlist, this.conlist.contacts);
this.http.createRequest('https://phpfiddle.org/api/run/code/json')
.asPost()
.withHeader('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8')
.withContent("code="+encphpcode)
.send()
.then(response => {
alert(response.response);
console.log(response);
var respobj = JSON.parse(response.response);
var respdataArr = JSON.parse(respobj.result);
this.api.setContactList(respdataArr);
console.log("a2", this.conlist, this.conlist.contacts, this.conlist.getThis(), Container.instance.get(ContactList));
}).catch(err => {
console.log(err);
})
;
}
...
...,我在contact-list.js
中添加了这个console.log语句:
... and I added this console.log statement in contact-list.js
:
created(){
this.api.getContactList().then(contacts => {
this.contacts = contacts;
console.log("b1", this, this.contacts); });
}
...以及contact-list.js
中的此功能:
... and also this function in contact-list.js
:
getThis(){
return this;
}
但是,当我运行此程序(单击开始的单击我"按钮后)时,在Chromium浏览器的错误日志中得到了此消息:
However, when I run this (after clicking the start "click me" button), I get this in the error log in Chromium browser:
VM2198 app-clist.js!transpiled:48
a1 ContactList {api: WebAPI, contacts: Array[0]} []
...
contact-list.js:21
b1 ContactList {api: WebAPI, __observers__: Object} [Object, Object, Object, Object, Object]
...
VM2198 app-clist.js!transpiled:55
a2 ContactList {api: WebAPI, contacts: Array[0]} []
ContactList {api: WebAPI, contacts: Array[0]}
ContactList {api: WebAPI, contacts: Array[0]}
...
所以,这就是我的解释方式:
So, here is how I interpret this:
- 消息
a1
打印在AppClist
类的constructor()
中-它首先运行;此时,通过注入使ContactList
类成为称为conlist
的AppClist
的类属性.此时,AppClist.conlist.contacts
(即,ContactList.contacts
)数组为空是可以理解的,并且大小为0. - 在
ContactList.contacts
数组已初始化后,当ContactList
组件为created()
时,将打印b1
消息,并第二次显示-再次,正如预期的那样,contacts
数组中有5个元素 - 在HTTP调用完成时将显示消息
a2
-我本来希望contacts
数组中有5个元素,但是有0个(无论使用哪种访问方法)?!
- Message
a1
is printed inconstructor()
ofAppClist
class - and it runs first; at that point, theContactList
class is made available through injection as a class property ofAppClist
calledconlist
. At this point, theAppClist.conlist.contacts
(that is,ContactList.contacts
) array is understandably empty, and has size 0. - Message
b1
is printed when theContactList
component iscreated()
, after theContactList.contacts
array has been initialized, and is printed second - again, as expected, there are 5 elements in thecontacts
array - Message
a2
is printed when the HTTP call is finished - I would have expected 5 elements in thecontacts
array, but there are 0 (regardless of access method) ?!
所以,我的问题是-为什么当应该至少为5时,为什么contacts
数组的大小为0? inject
是否可能缓存应该引用的变量/类的状态?如何获得对AppClist
类中ContactList
类的contacts
数组属性的最新状态的引用?
So, my question is - why do I get 0 as size of the contacts
array, when there should be at least 5? Does the inject
maybe cache the state of the variable/class it is supposed to reference? How can I get a reference to the latest state of the contacts
array property of ContactList
class in the AppClist
class?
推荐答案
好吧,我想我找到了一个解决方法-尽管这只是一些猜测,所以我仍然希望有人提供正确的答案.
Well, I think I found a fix - although this is all a bit of guesswork, so I would still appreciate a proper answer from someone.
首先,我认为问题是缓存",但看起来更有可能,例如Container.instance.get(ContactList)
返回该类的 new 实例,而不是现有的实例.实例.这是我发现的一些相关报价:
First, I thought the issue was "caching", but it looks like it is far more likely, that for instance Container.instance.get(ContactList)
returns a new instance of the class, rather than the one existing instance. Here are some relevant quotes I found:
增强的依赖注入用法·问题#73·aurelia/dependency-injection·GitHub 建议使用以下方法:
// configure the container
let container = aurelia.container;
container.registerInstance(ApiClient, new ApiClient(isDebug));
...
aurelia.start().then(a => a.setRoot());
...
...-我尝试将其应用于 ... in 如果Aurelia理解"import",为什么要使用依赖注射? 这是因为Aurelia的依赖注入容器正在为您实例化一个实例. ... This is because Aurelia's Dependency Injection container is instantiating an instance for you. ... 嗯,在我的示例中,当我们到达"a2"日志时,DI应该已经知道"它已经创建了一个 Hmm, well, in my example, by the time we get to the "a2" log, the DI should already "know" that it already had created one 默认情况下,DI容器假定一切都是单例实例;该应用的一个实例.但是,您可以使用注册修饰符来更改此设置. By default, the DI container assumes that everything is a singleton instance; one instance for the app. However, you can use a registration decorator to change this. 好吧,在上面的示例中,显然没有假设 Well, apparently it didn't assume that for The solution for me came from the other answer in the previous post, How to create a singleton service in Aurelia?: 所以我意识到我在想这个太难了.我试图依靠框架(Aurelia)来完成所有工作,但实际上,这是一个简单的ES6类更改,使其成为了实例. So I realized I was thinking about this too hard. I was trying to depend on the framework (Aurelia) to do all the work, but actually it was a simple ES6 class change that makes it an instance. ...,这就是我将其应用于 ... and here is how I applied that to the 有了这个,显然 With this, apparently the 这也意味着现在 That means also that now 这篇关于Aurelia-通过注入访问更新的类属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!ContactList
类,但无法使我的示例正常工作... main.js
- I tried applying this to the ContactList
class, but couldn't get my example to work...
您正在告诉Aurelia:我需要其中之一,请给我."而Aurelia说:当然,我已经创建了一个,或者我已经有一个在附近了,就在这里."
You are telling Aurelia "I need one of these, please give it to me," and Aurelia says "Sure thing, I've created one or I already had one lying around, here it is."ContactList
-但是它显然仍然仍然创建了一个新对象. .. ContactList
- but it apparently still creates a new object anyway...
ContactList
是这样的!! ContactList
in the example above ?!
ContactList
类的方法,并添加了一个cl_instance
变量:ContactList
class, adding a cl_instance
variable:import {EventAggregator} from 'aurelia-event-aggregator';
import {WebAPI} from './web-api';
import {ContactUpdated, ContactViewed} from './messages';
let cl_instance = null;
export class ContactList {
static inject = [WebAPI, EventAggregator];
constructor(api, ea){
if(!cl_instance) {
cl_instance = this;
this.api = api;
this.contacts = [];
ea.subscribe(ContactViewed, msg => this.select(msg.contact));
ea.subscribe(ContactUpdated, msg => {
let id = msg.contact.id;
let found = this.contacts.find(x => x.id === id);
Object.assign(found, msg.contact);
});
} // end if!
return cl_instance;
}
....
ContactList
类现在表现得像一个单例(?!),因此每次我请求引用一个类实例时,我都会得到相同的类实例(而不是实例化一个新的实例). ).ContactList
class now behaves as a singleton (?!), and so everytime I ask for a reference to a class instance, I'll get the same class instance (and not instantiate a new one).AppClist
中的this.conlist.contacts
引用了ContactList
中的实际数据源contacts
属性变量,因此现在为其分配将触发绑定并更新GUI-这样就解决了问题 Aurelia JS-发出同步HTTP请求,以便在页面加载之前更改数据?-我已将该示例保存为 https://gist.run/?id=f4bd01c99f9973cb76d8640f6248c2e3 this.conlist.contacts
in AppClist
refers to the actual datasource contacts
property variable in ContactList
, and thus assigning to it now triggers the binding and updates the GUI - which thus solves the problem in Aurelia JS - Making a synchronous HTTP request, to change data before page load? - I've saved that example for reference on https://gist.run/?id=f4bd01c99f9973cb76d8640f6248c2e3