2017-01-30 10 views
0

我还在试图寻找一个答案,Aurelia JS - Making a synchronous HTTP request, to change data before page load? - 所以我想在这个问题,https://gist.run/?id=90d98563621fe49c1dde6b4f2fc6961d代码示例如下。Aurelia - 从注入访问更新的类属性?

根据Aurelia - how to change bound variables, so the GUI changes?,我知道我可以更改一个类变量,它是HTML绑定的源,并且HTML/GUI应该更新。所以我想在上面的要点类似的东西 - 特别是,我试图改变ContactList类的contacts阵列属性(在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'} = '[email protected]'; 
$tObj->{'phoneNumber'} = '243-6593'; 
array_push($outarr, $tObj); 
$tObj = new StdClass(); 
$tObj->{'id'} = '2'; 
$tObj->{'firstName'} = 'Chad'; 
$tObj->{'lastName'} = 'Connor'; 
$tObj->{'email'} = '[email protected]'; 
$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:

created(){ 
    this.api.getContactList().then(contacts => { 
     this.contacts = contacts; 
     console.log("b1", this, this.contacts); }); 
    } 

...而且这个功能在contact-list.js

getThis(){ 
    return this; 
    } 

但是,当我运行这个(点击开始后,“点击我”按钮),我得到这个错误日志中Chromium浏览器:

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]} 
... 

所以,这里是我如何解释这一点:

  • 消息a1打印在AppClist类的constructor() - 它首先运行;在这一点上,ContactList类是通过注射的所谓conlistAppClist类属性可用。在这一点上,AppClist.conlist.contacts(即,ContactList.contacts)阵列是可以理解的空的,并且具有大小为0
  • ContactList组分是created(),消息b1被印刷在ContactList.contacts阵列已经被初始化之后,并且第二印刷 - 再次如预期的那样,contacts阵列中有5个元素
  • 消息a2在HTTP调用完成时会打印 - 我期望在contacts阵列中有5个元素,但是有0个(不管访问方法如何)?

所以,我的问题是 - 为什么我得到0作为contacts阵列的大小,至少应该有5个? inject可能缓存它应该引用的变量/类的状态吗?我怎样才能得到在AppClist类的contacts阵列属性ContactList类的最新状态?

回答

0

嗯,我想我找到了一个解决方法 - 虽然这全是一些猜测,所以我仍然会很欣赏某人的正确答案。

首先,我认为这个问题是“缓存”,但它看起来更有可能,即例如Container.instance.get(ContactList)返回类的实例,而不是一个现有的实例。下面是我发现一些相关报价:

Enhanced Dependency Injection Use · Issue #73 · aurelia/dependency-injection · GitHub建议使用这样的:

// configure the container 
    let container = aurelia.container; 
    container.registerInstance(ApiClient, new ApiClient(isDebug)); 
    ... 
    aurelia.start().then(a => a.setRoot()); 
    ... 

...在main.js - 我试图将其应用到了ContactList类,但不能让我的例子工作...

​​

这是因为Aurelia的依赖注入容器正在为您实例化一个实例。 ...
你在告诉Aurelia“我需要其中的一个,请把它交给我,”Aurelia说:“当然,我已经创建了一个,或者我已经有一个躺在这里,在这里。”

嗯,好了,在我的例子,通过时间我们得到的“A2”登录时,DI应该已经“知道”它已经创造了一个ContactList - 但它显然还创建了一个新的对象呢...

How to create a singleton service in Aurelia?

默认情况下,DI容器假定一切都是单一实例;一个应用程序实例。但是,您可以使用注册装饰器来更改它。

那么,显然它并没有假设为ContactList在上面的例子?!

对我来说,解决方案从对方的回答排在以前的帖子,How to create a singleton service in Aurelia?

所以我意识到,我想这个太难了。我试图依靠框架(Aurelia)来完成所有的工作,但实际上这是一个简单的ES6类更改,使它成为一个实例。

...这里是我如何应用该到ContactList类,添加一个cl_instance变量:(?!)

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类现在的行为作为一个单身,所以每次我要求引用一个类实例时,我都会得到相同的类实例(而不是实例化一个新实例)。

这也意味着现在this.conlist.contactsAppClist是指实际的数据源contacts属性变量在ContactList,因此分配给它现在触发绑定和更新GUI - 这从而解决了Aurelia JS - Making a synchronous HTTP request, to change data before page load?这个问题 - 我已经保存的举例https://gist.run/?id=f4bd01c99f9973cb76d8640f6248c2e3