Aurelia-通过注入访问更新的类属性? [英] Aurelia - accessing updated class properties from injection?

查看:82
本文介绍了Aurelia-通过注入访问更新的类属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我仍在寻找 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类成为称为conlistAppClist的类属性.此时,AppClist.conlist.contacts(即,ContactList.contacts)数组为空是可以理解的,并且大小为0.
  • ContactList.contacts数组已初始化后,当ContactList组件为created()时,将打印b1消息,并第二次显示-再次,正如预期的那样,contacts数组中有5个元素
  • 在HTTP调用完成时将显示消息a2-我本来希望contacts数组中有5个元素,但是有0个(无论使用哪种访问方法)?!
  • Message a1 is printed in constructor() of AppClist class - and it runs first; at that point, the ContactList class is made available through injection as a class property of AppClist called conlist. At this point, the AppClist.conlist.contacts (that is, ContactList.contacts) array is understandably empty, and has size 0.
  • Message b1 is printed when the ContactList component is created(), after the ContactList.contacts array has been initialized, and is printed second - again, as expected, there are 5 elements in the contacts array
  • Message a2 is printed when the HTTP call is finished - I would have expected 5 elements in the contacts 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());
  ...

中的

...-我尝试将其应用于ContactList类,但无法使我的示例正常工作...

... in main.js - I tried applying this to the ContactList class, but couldn't get my example to work...

如果Aurelia理解"import",为什么要使用依赖注射?

这是因为Aurelia的依赖注入容器正在为您实例化一个实例. ...
您正在告诉Aurelia:我需要其中之一,请给我."而Aurelia说:当然,我已经创建了一个,或者我已经有一个在附近了,就在这里."

This is because Aurelia's Dependency Injection container is instantiating an instance for you. ...
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."

嗯,在我的示例中,当我们到达"a2"日志时,DI应该已经知道"它已经创建了一个ContactList-但是它显然仍然仍然创建了一个新对象. ..

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 ContactList - but it apparently still creates a new object anyway...

如何在Aurelia中创建单例服务?

默认情况下,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.

好吧,在上面的示例中,显然没有假设ContactList是这样的!!

Well, apparently it didn't assume that for ContactList in the example above ?!

为我提供的解决方案来自上一篇文章

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.

...,这就是我将其应用于ContactList类的方法,并添加了一个cl_instance变量:

... and here is how I applied that to the 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类现在表现得像一个单例(?!),因此每次我请求引用一个类实例时,我都会得到相同的类实例(而不是实例化一个新的实例). ).

With this, apparently the 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

That means also that now 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

这篇关于Aurelia-通过注入访问更新的类属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆