Aurelia通用类/模型

Aurelia通用类/模型,aurelia,Aurelia,我试图在Aurelia项目中实现一个全局可访问的单类。其目的是(a)存储奇点/状态(如当前用户ID/名称/权限),(b)加载和存储公共数据(如整个应用程序中下拉列表的枚举列表和键值对),(c)存储常用函数(如Http Fetch client的包装器),(d)配置并更新i18n语言环境,(e)整个应用程序热键的全局键盘侦听器。以下是我目前掌握的情况: /src/resources/components/core.js: import 'fetch'; import { HttpClient, j

我试图在Aurelia项目中实现一个全局可访问的单类。其目的是(a)存储奇点/状态(如当前用户ID/名称/权限),(b)加载和存储公共数据(如整个应用程序中下拉列表的枚举列表和键值对),(c)存储常用函数(如Http Fetch client的包装器),(d)配置并更新i18n语言环境,(e)整个应用程序热键的全局键盘侦听器。以下是我目前掌握的情况:

/src/resources/components/core.js

import 'fetch';
import { HttpClient, json } from 'aurelia-fetch-client';
import { inject } from 'aurelia-framework';
import { EventAggregator } from 'aurelia-event-aggregator';
import { BindingSignaler } from 'aurelia-templating-resources';
import { I18N } from 'aurelia-i18n';
import * as store from 'store';

@inject(EventAggregator, BindingSignaler, I18N, HttpClient)
export class Core {

  constructor(eventAggregator, bindingSignaler, i18n, httpClient) {
    // store local handles
    this.eventAggregator = eventAggregator;
    this.bindingSignaler = bindingSignaler;
    this.i18n = i18n;

    // initialize singulars
    this.UserID = 1;
    this.lang = 'es';
    this.yr = 78;
    this.qtr = 1;

    // set up httpClient
    httpClient.configure(config => {
      config
        .withBaseUrl('http://localhost:8080/api/v1');
    });
    this.httpClient = httpClient;

    // listen for Ctrl+S or Ctrl+Enter and publish event
    window.addEventListener("keydown", (event) => {
      if (event.ctrlKey || event.metaKey) { // Ctrl + ___
        if ((event.keyCode == 83) || (event.keyCode == 115) || (event.keyCode == 10) || (event.keyCode == 13)) {  // Ctrl+Enter or Ctrl+S
          // Save button... publish new event
          event.preventDefault();
          this.eventAggregator.publish('ewKeyboardShortcutSave', true);
        }
        if ((event.keyCode == 77) || (event.keyCode == 109)) {  // Ctrl+M
          // New button... publish new event
          event.preventDefault();
          this.eventAggregator.publish('ewKeyboardShortcutNew', true);
        }
      }
    });

    // load enumData
    $.getJSON("../../locales/" + this.lang + "/enum.json", (json) => { this.enum = json; });
    this.getTableKeys();
    this.getEnumCats();
  }

  getData(url) {
    // Http Fetch Client to retreive data (GET)
    return this.httpClient.fetch(url)
      .then(response => response.json());
  }

  postData(url, data, use_method = 'post') {
    // Http Fetch Client to send data (POST/PUT/DELETE)
    return this.httpClient.fetch(url, {
      method: use_method,
      body: json(data)
    }).then(response => {
      if (!response.ok) {
        throw Error(response.statusText);
      }
      return response;
    });
  }

  getTableKeys() {
    // retrieve list of table keys from database API
    this.getData('/keys').then(response => {
      this.keys = response;
    });
  }

  getEnumCats() {
    // retrieve list of enum cats from database API
    this.getData('/enums').then(response => {
      this.cats = response;
    });
  }

  setLang(lang) {
    if (lang) {
      this.lang = lang;
    }
    // set i18n locale
    this.i18n.setLocale(this.lang);
    // load enumData
    $.getJSON("../../locales/" + this.lang + "/enum.json", (json) => {
      this.enumData = json;
    });
    // publish new event
    this.eventAggregator.publish('ewLang', lang);
    this.bindingSignaler.signal('ewLang');
  }
}
以下是资源特性的/src/resources/index.js

export function configure(config) {

  // value converters
  config.globalResources([
    './value-converters/currency-format-value-converter',
    './value-converters/number-format-value-converter',
    './value-converters/date-format-value-converter',
    './value-converters/checkbox-value-converter',
    './value-converters/keys-value-converter',
    './value-converters/enum-value-converter',
    './value-converters/table-key-value-converter'
    ]);

  // custom elements
  config.globalResources([
    './elements/enum-list',
    './elements/modal-form'
    ]);

  // common/core components
  config.globalResources([
    './components/core'
    ]);
}
它在mymain.js中依次被激活,如下所示:

export function configure(aurelia) {
  aurelia.use
    .standardConfiguration()
    .feature('resources')
    // .plugin('aurelia-dialog') // not working
    .plugin('aurelia-validation')
    .plugin('aurelia-i18n', (instance) => {
      // register backend plugin
      instance.i18next.use(XHR);
      instance.setup({
        backend: {                                  
          loadPath: '/locales/{{lng}}/{{ns}}.json',
        },
        lng : 'en',
        ns: ['translation'],
        defaultNS: 'translation',
        attributes : ['t'],
        fallbackLng : 'en',
        debug : false
      });
    });

  aurelia.start().then(a => a.setRoot());
}
export function configure(aurelia) {
   //...

   Core core = new Core(); //<--- put necessary parameters
   //some default configuration
   aurelia.container.registerInstance(Core, core);      

  aurelia.start().then(a => a.setRoot());
}
问题:

  • 它不起作用了。我得到两个错误:
    vendor bundle.js:3777 Uncaught TypeError:h.load不是函数
    未处理的拒绝错误:模块加载超时:模板注册表项!参考资料/components/core.html,文本!参考资料/components/core.html
    。当我只需要core.js组件时,你知道为什么它会试图找到core.html吗

  • 甚至可以全局注入这种类型的类,而我的viewmodels不需要注入它,但仍然可以访问属性,或者我仍然需要到处注入这个文件吗

  • 文件名core.js和类名core是否可以接受命名约定?在/src/resources/components中的位置是一个不错的选择吗?我必须创建components子文件夹

  • 关于更好的最佳实践还有其他建议吗


  • 问题1

    执行此操作时:

    config.globalResources([
    './components/core'
    ]);
    
    Aurelia将尝试加载一对视图和视图模型,分别为core.jscore.html,除非组件声明为“仅视图模型组件”。像这样:

    import { noView } from 'aurelia-framework';
    
    @noView
    @inject(EventAggregator, BindingSignaler, I18N, HttpClient)
    export class Core {
    }
    
    在上述情况下,Aurelia不会尝试加载“core.html”,因为组件是用
    noView
    声明的

    问题2

    据我所知,你必须
    注入
    它无处不在,但后者不适用于你的情况,所以你必须
    注入
    。你可以用一些诡计来避免注射,但我不推荐

    问题3

    文件名core.js和类名
    core
    不仅是可以接受的,而且是正确的方法。然而,我不认为“/resources/components”是一个好位置,因为它不是一个组件,甚至不是一个“资源”。我会把这个移到另一个文件夹

    此外,请拆下以下线路:

    config.globalResources([
    './components/core'
    ]);
    
    资源是用来在视图中使用的,这不是您的情况

    问题4

    文件core.js似乎是应用程序中非常重要的一段代码。我会把它放在根文件夹中,紧挨着main.js。(这是我的意见)

    另外,如果您需要在
    核心
    对象中设置一些特定属性,您可以在main.js中实例化它。大概是这样的:

    export function configure(aurelia) {
      aurelia.use
        .standardConfiguration()
        .feature('resources')
        // .plugin('aurelia-dialog') // not working
        .plugin('aurelia-validation')
        .plugin('aurelia-i18n', (instance) => {
          // register backend plugin
          instance.i18next.use(XHR);
          instance.setup({
            backend: {                                  
              loadPath: '/locales/{{lng}}/{{ns}}.json',
            },
            lng : 'en',
            ns: ['translation'],
            defaultNS: 'translation',
            attributes : ['t'],
            fallbackLng : 'en',
            debug : false
          });
        });
    
      aurelia.start().then(a => a.setRoot());
    }
    
    export function configure(aurelia) {
       //...
    
       Core core = new Core(); //<--- put necessary parameters
       //some default configuration
       aurelia.container.registerInstance(Core, core);      
    
      aurelia.start().then(a => a.setRoot());
    }
    
    导出功能配置(aurelia){ //... Core Core=new Core();//a.setRoot()); } 现在,您可以使用
    @inject
    装饰器插入
    core
    对象,所有类都将具有相同的
    core
    实例。更多信息请访问


    希望这有帮助

    法比奥,非常感谢你如此彻底的回复。如果我能邀请它10次,我会的//我收到一个错误
    TypeError:无法读取新内核中未定义的属性“configure”
    。我想知道“必要的参数”是否相关,但我不知道这些参数是什么,也不知道如何修复它。如果
    Core
    类的构造函数中有参数,那么这只是一个示例。。。你不会放弃第一个核心,因为此时还没有核心。。。是的,基于core.js的代码,没有默认配置,您可以跳过该步骤