javascript - Aurelia - 如何为 ViewCompiler 注册 View 资源?

标签 javascript aurelia aurelia-templating

我有一个基于行(类似表格)的自定义元素,它根据可绑定(bind)的列属性动态呈现其模板。它以字符串形式组成行模板,并使用 ViewCompilerViewFactoryView 进行渲染。

import {inject} from 'aurelia-dependency-injection';
import {bindable, ViewCompiler, ViewResources} from 'aurelia-templating';

@inject(ViewCompiler, ViewResources)
export class MyDynamicGrid {
    @bindable columns: any[];
    @bindable rows: any[];

    constructor(viewCompiler: ViewCompiler, viewResources: ViewResources) {
        const template = '<template><custom-element></custom-element></template>'; //this is rather complex in practice

        viewResources.registerElement('custom-element', /* HtmlBehaviorResource? */);
        this._viewFactory = viewCompiler.compile(template, viewResources);
    }

    _render() : void {
        const view = this._viewFactory.create(/* some container */);
        view.bind(someContext, someOverrideContext);
        //attach view to the DOM
    }
}

这工作正常,直到自定义模板包含标准 HTML 元素。一旦我开始将自定义元素放入模板中,它就会停止工作。它仍然呈现 HTML,但 Aurelia 不会附加自定义元素的行为。

我知道,所有自定义元素都应该“注册”才能使用。 “正常注册”发生在通过 <require> 的 View 中,或在 View 模型 @viewResources 中,或在全局注册。

但是,在这种特殊情况下,注入(inject)的 ViewCompiler仅继承 View 模型父级的 View 资源。我的问题是:如何注册任何其他 View 资源?我知道 ViewCompiler 中的第二个参数。的compile方法,但无法使其发挥作用。如果我在全局范围内注册它,我能够使其发挥作用的唯一方法。

注意:这个问题的重点是注册 View 资源。动态渲染效果很好

最佳答案

我通过深入研究 docs+github 找到了解决方案。我为两种不同的方法创建了两个示例:

  1. 手动创建HtmlBehaviorResource实例,用于注册一个特定元素。

示例(基于:https://github.com/aurelia/templating-resources/blob/master/test/repeat-integration.spec.js)

import {CustomElement} from 'my-components/my-custom-element';
import {inject, Container} from 'aurelia-dependency-injection';
import {ViewCompiler, ViewResources} from 'aurelia-templating';
import {metadata} from 'aurelia-metadata';

@inject(ViewCompiler, ViewResources, Container)
export class MyDynamicGrid {

    //bindables and constructor is ommitted

    init(): void {
        const resource: HtmlBehaviorResource = metadata.get(metadata.resource, CustomElement);
        resource.initialize(this._container, CustomElement);
        resource.load(this._container, CustomElement)
            .then(() => {
                resource.register(this._viewResources);

                this._viewFactory = viewCompiler.compile(template, this._viewResources);
            });
    }
}

备注:resource.register(this._viewResources); 行等效于 this._viewResources.registerElement('custom-element', resource);。唯一的区别是首先从约定或装饰器中读取名称。

  • 使用 ViewEngine 并导入整个模块。如果导入多个资源,甚至是不同类型(属性、元素、转换器等)并且来自不同文件,则这种方法更合适。
  • 示例:

    import {CustomElement} from 'my-components/my-custom-element';
    import {inject} from 'aurelia-dependency-injection';
    import {ViewCompiler, ViewResources, ViewEngine} from 'aurelia-templating';
    
    @inject(ViewCompiler, ViewResources, ViewEngine)
    export class MyDynamicGrid {
    
        //bindables and constructor is ommitted
    
        init(): void {
            this._viewEngine
                .importViewResources(['my-components/my-custom-element'], [undefined], this._viewResources)
                .then(() => {
                    this._viewFactory = viewCompiler.compile(template, this._viewResources);
                });
        }
    }
    

    关于javascript - Aurelia - 如何为 ViewCompiler 注册 View 资源?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41468304/

    相关文章:

    Aurelia 无需 compose 即可动态创建自定义元素

    Aurelia - 提高repeat.for View 渲染的性能

    javascript - 使用 Ajax 更新 Github 问题正文

    asp.net-core - Aurelia 不加载没有哈希值的 URL

    javascript - 在 Aurelia 中聚焦一个元素

    javascript - Bootstrap 4 Beta 使用 Webpack 3.x 导入 Popper.js 抛出 Popper is not a constructor

    html - Aurelia:模板中有多个插槽?

    javascript - jquery-ui.widget 中的 "base"函数未定义?

    javascript - 在 AngularJS 指令中调用传入的函数

    javascript - 如何改进 JavaScript 中的 if else 结构?