Как снести расширенный фрагмент
Я работаю над существующим SPA, где мы постепенно заменяем компоненты компонентами Aurelia. Мы используем enhance
API TemplatingEngine
, Это работает довольно хорошо, но мы также должны разрушить эти расширенные фрагменты (удалить прослушиватели событий,...) при переходе в другую часть приложения (без перезагрузки страницы).
Моя идея - сохранить экземпляр aurelia на странице и использовать его повторно.
В настоящее время я улучшаю фрагменты как это:
function enhanceFragment(targetElement) {
function proceed() {
let aurelia = window.DFAurelia;
let engine = aurelia.container.get(TemplatingEngine);
engine.enhance({
container: aurelia.container,
element: targetElement,
resources: aurelia.resources
});
}
if (!window.DFAurelia) {
bootstrap(async aurelia => {
aurelia.use
.defaultBindingLanguage()
.defaultResources()
.eventAggregator()
.developmentLogging()
.globalResources('app/df-element');
await aurelia.start();
window.DFAurelia = aurelia;
proceed();
});
} else {
proceed();
}
}
HTML-код, который я улучшаю, выглядит так:
<df-element></df-element>
Я попробовал это в функции самого пользовательского элемента (DfElement::removeMyself()
):
let vs: ViewSlot = this.container.get(ViewSlot);
let view: View = this.container.get(View);
vs.remove(view);
vs.detached();
vs.unbind();
но я получаю ошибку при получении представления из контейнера (Невозможно прочитать свойство 'resources' undefined). Я вызвал эту функцию из обработчика кликов.
Основной вопрос: как вручную вызвать unbind
а также detached
крючки DfElement
а его дети?
Бонусные вопросы: свойства моего aurelia
пример (window.DFAurelia
) root
а также host
не определены: это плохо? Видите ли вы какие-либо потенциальные проблемы с этим способом улучшения (и не усиления) фрагментов на странице?
1 ответ
Использовать View
вернулся из enhance()
метод.
enhance()
метод возвращает расширенный View
объект. Рекомендуется управлять демонтажем из того же места, где вы звоните. enhance()
, так как вы не сможете доверять элементу, чтобы не забыть разрушить себя. Тем не менее, вы всегда можете зарегистрировать View
экземпляр с контейнером расширения для доступа к нему из пользовательского элемента.
function proceed() {
let aurelia = window.DFAurelia;
let container = aurelia.container;
let engine = container.get(TemplatingEngine);
let view = engine.enhance({
container: container,
element: targetElement,
resources: aurelia.resources
});
container.registerInstance(View, view);
}
Это скажет контейнеру DI отвечать на вызовы для View
с этим View
,
import { inject, Aurelia, View } from 'aurelia-framework';
@inject(Aurelia, Element)
export class DFCustomElement {
// element is passed to the constructor
constructor(aurelia, element) {
this.container = aurelia.container;
this.element = element;
}
// but View is only available after attached
attached() {
this.view = this.container.get(View);
}
removeMyself() {
this.element.remove();
this.view.detached();
this.view.unbind();
}
}
С использованием created(view)
метод жизненного цикла
Гораздо лучшей практикой будет использование created(view)
метод жизненного цикла в вашем пользовательском элементе.
import { inject } from 'aurelia-framework';
@inject(Element)
export class DFCustomElement {
constructor(element) {
this.element = element;
}
created(view) {
this.view = view;
}
removeMyself() {
this.element.remove();
this.view.detached();
this.view.unbind();
}
}
Это гораздо более простой и эффективный способ получить собственный элемент View
, Однако, пытаясь написать этот ответ для вас, я протестировал вложение пользовательского элемента в <compose>
элемент. Результатом было то, что View
в моем пользовательском элементе был на самом деле View
для меня <compose>
элемент и removeMyself()
удалил <compose>
полностью.