【问题标题】:Aurelia common class/modelAurelia 通用类/型号
【发布时间】:2016-11-11 17:22:21
【问题描述】:

我正在尝试在 Aurelia 项目中实现一个全局可访问的奇异类。目的是 (a) 存储单数/状态,如当前用户 ID/名称/权限,(b) 加载和存储通用数据,如枚举列表和整个应用程序中下拉列表的键值对,(c) 存储常用功能,例如 Http-Fetch 客户端的包装器,(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'
    ]);
}

这又在我的 ma​​in.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());
}

问题:

  1. 它不工作。我收到两个错误:vendor-bundle.js:3777 Uncaught TypeError: h.load is not a functionUnhandled rejection Error: Load timeout for modules: template-registry-entry!resources/components/core.html,text!resources/components/core.html。知道为什么当我只需要 core.js 组件时它试图找到 core.html 吗?

  2. 是否可以全局注入这种类型的类,使我的视图模型不需要注入它但仍然可以访问属性,还是我仍然需要在任何地方注入这个文件?

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

  4. 还有其他更好的最佳实践建议吗?

【问题讨论】:

    标签: aurelia


    【解决方案1】:

    问题 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

    据我所知,您必须在任何地方使用inject<require>,但后者不适用于您的情况,因此您必须使用inject。您可以采取一些技巧来避免注入,但我不推荐。

    问题 3

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

    此外,删除这些行:

    config.globalResources([
    './components/core'
    ]);
    

    资源被用于视图内部,这不是你的情况。

    问题 4

    core.js 文件似乎是您的应用程序中非常重要的一段代码。我会把它放在根文件夹中,在 ma​​in.js 旁边。 (这是我的意见)

    另外,如果您需要在 Core 对象中设置一些特定属性,您可以在 ma​​in.js 中对其进行实例化。像这样的:

    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());
    }
    

    现在,您可以使用@inject 装饰器注入core 对象,并且所有类都将具有相同的Core 实例。更多信息http://aurelia.io/hub.html#/doc/article/aurelia/dependency-injection/latest/dependency-injection-basics/1

    希望这会有所帮助!

    【讨论】:

    • 法比奥,非常感谢您如此彻底的回复。如果我能邀请它 10 次,我会的。
    • Core core = new Core(); //&lt;--- put necessary parameters 行,2 个问题:(1)这是 TypeScript 吗?我正在使用 ESNext 并认为我会放弃第一个核心? (2) 基于core.js的代码,不会有任何参数或默认配置吧?
    • 我收到一个错误TypeError: Cannot read property 'configure' of undefined at new Core。我想知道“必要参数”是否相关,但我不知道这些是什么或如何解决它。
    • 这只是一个示例,如果Core 类在构造函数中具有参数,则可以使用...您不会删除第一个核心,因为此时还没有核心...是的,基于core.js的代码没有默认配置,你可以跳过这一步
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-25
    • 1970-01-01
    • 2017-09-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多