Аурелия общий класс / модель
Я пытаюсь реализовать общедоступный единственный класс в проекте Aurelia. Цели заключаются в том, чтобы (а) сохранять отдельные состояния / состояния, такие как текущий идентификатор пользователя / имя / разрешения, (б) загружать и хранить общие данные, такие как списки перечислений и пары ключ-значение, для раскрывающихся списков по всему приложению, (в) хранить часто используемые функции, такие как оболочки для клиента 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.html, когда мне нужен только компонент core.js?Можно ли даже глобально внедрить этот тип класса таким образом, чтобы моим моделям представления не нужно было внедрять его, но он все еще мог получить доступ к свойствам, или мне все еще нужно внедрять этот файл везде?
Является ли имя файла core.js и имя класса Core приемлемыми для именования? Является ли расположение внутри / src / resources / components хорошим выбором? Я должен был создать подпапку компонентов.
Любые другие предложения для лучшей передовой практики?
1 ответ
Вопрос 1
Когда вы делаете это:
config.globalResources([
'./components/core'
]);
Aurelia попытается загрузить пару view и view-model, соответственно core.js и core.html, если только компонент не объявлен как "компонент только для view-модели". Как это:
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
декоратор и все классы будут иметь один и тот же экземпляр Core
, Более подробная информация на http://aurelia.io/hub.html#/doc/article/aurelia/dependency-injection/latest/dependency-injection-basics/1.
Надеюсь это поможет!