Как снести расширенный фрагмент

Я работаю над существующим 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> полностью.

Другие вопросы по тегам