我正在尝试在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'
]);
}
又在我的 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());
}
问题:
它不起作用。我收到两个错误:vendor-bundle.js:3777 Uncaught TypeError: h.load is not a function
和Unhandled rejection Error: Load timeout for modules: template-registry-entry!resources/components/core.html,text!resources/components/core.html
。知道为什么当我只需要core.js组件时它试图找到core.html吗?
甚至可以以我的viewmodels不需要注入但仍然可以访问属性的方式全局注入这种类,或者我是否还需要在任何地方注入此文件?
文件名 core.js 和班级名称核心是否可接受的命名约定? / src / resources / components里面的位置是个不错的选择吗?我必须创建组件子文件夹。
有关更好的最佳做法的其他建议吗?
答案 0 :(得分:4)
问题1
执行此操作时:
config.globalResources([
'./components/core'
]);
Aurelia将尝试加载一对视图和视图模型,分别为 core.js 和 core.html ,除非该组件被声明为“视图” -model only component“。像这样:
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 似乎是您应用程序的一个非常重要的代码段。我会把它放在 main.js 旁边的根文件夹中。 (这是我的观点)
此外,如果您需要在Core
对象中设置一些特定属性,则可以在 main.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());
}
现在,您可以使用core
装饰器注入@inject
对象,并且所有classe将具有相同的Core
实例。有关更多信息,请访问http://aurelia.io/hub.html#/doc/article/aurelia/dependency-injection/latest/dependency-injection-basics/1
希望这有帮助!