【问题标题】:How to tear down an enhanced fragment如何拆除增强的片段
【发布时间】:2017-01-16 14:24:42
【问题描述】:

我正在开发一个现有的 SPA,我们逐步将组件替换为 Aurelia 组件。我们使用TemplatingEngineenhance API。这工作得很好,但我们还需要在移动到应用程序的另一部分(不重新加载页面)时拆除那些增强的片段(删除事件侦听器,...)。

我的想法是将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();

但从容器获取视图时出现错误(无法读取未定义的属性“资源”)。我从点击处理程序中调用了这个函数。

主要问题:如何手动触发DfElement 及其子级的unbinddetached 钩子

额外问题:我的 aurelia 实例 (window.DFAurelia) roothost 的属性未定义:这是一件坏事吗?您认为这种增强(和不增强)页面片段的方式有什么潜在的问题吗?

【问题讨论】:

    标签: aurelia aurelia-templating


    【解决方案1】:

    使用从enhance() 方法返回的View

    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 的更直接、最佳实践的方法。但是,在尝试为您编写此答案时,我测试了将自定义元素嵌套在 &lt;compose&gt; 元素中。结果是我的自定义元素中的View 实际上是我的&lt;compose&gt; 元素的View,而removeMyself() 完全删除了&lt;compose&gt;

    【讨论】:

    • 我不使用&lt;compose&gt; 作为这个元素,所以第二个选项对我有用。谢谢!
    • this.view = null; 作为removeMyself 的最后一行重要吗?
    • 对于垃圾收集器?
    • 嗨 Matthew,您能否详细说明一下“从调用增强 () 的同一位置管理拆解是一个好习惯,因为您可能无法信任某个元素记得把自己拆掉。”据我了解,这不是您在代码示例中涵盖的内容?
    猜你喜欢
    • 2018-11-11
    • 1970-01-01
    • 2021-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-21
    • 1970-01-01
    相关资源
    最近更新 更多