在aurelia中组成html文件 [英] composing html file in aurelia

查看:48
本文介绍了在aurelia中组成html文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在aurelia中实现类似于android中"include"的功能:

I'd like to achieve something similar as "include" in android but in aurelia:

如何在父视图中评估绑定并且不使用自定义元素的情况下,将纯HTML文件内容注入到我的视图中? 绑定innerhtml是不够的,因为根据文档,绑定表达式被绕过了.

How to inject a plain html file content into my view, with binding evaluated within the parent View, and without using a custom element? Binding innerhtml is not enough as, according to the doc, the bindings expressions are bypassed.

推荐答案

正如Ashley所言,使用<compose view="./your-view.html"></compose>元素将与现有的HTML文件一起使用,并将继承父上下文.

As already said by Ashley, using <compose view="./your-view.html"></compose> element will work with an existing HTML file and it will inherit the parent context.

如果要动态组成HTML(从文件,数据库或以编程方式构建),则使用ViewCompiler将为您提供最佳的性能和灵活性,因为与compose相比,这层要比compose小一层aurelia如何在内部构建自定义元素.

If you want to compose HTML dynamically (from a file, database, or built-up programmatically) then using the ViewCompiler will give you the best performance and flexibility, as this is one layer less than compose compared to how aurelia builds custom elements internally.

我在这里对另一个不同但相关的问题给出了类似的答案:

I gave a similar answer to a different (but related) question here:

Aurelia动态绑定

您将使用text插件将HTML文件作为文本加载到变量中,然后将其传递给ViewCompiler.我为此有一个自定义元素,就性能而言,它可能并不比compose好,但是在使用原始html作为输入时,它确实允许更多控制,并且您可以根据需要针对自己的情况进行自己的性能优化:

You'd use the text plugin to load your HTML file as text into a variable, and then pass that to the ViewCompiler. I have a custom element for this which, in terms of performance, is probably not better than compose but it does allow for more control when working with raw html as input and you could do your own performance optimizations specific to your situation as needed:

import * as markup from "text!./your-element.html";

export class SomeViewModel {
    constructor() {
        this.markup = markup;
    }
}

视图:

<template>
    <dynamic-html html.bind="markup"></dynamic-html>
</template>

出于完整性考虑,这是我将ViewCompiler封装在的自定义元素:

For completeness sake, here is the custom element I encapsulated the ViewCompiler in:

import {
    customElement,
    TaskQueue,
    bindable,
    ViewCompiler,
    ViewSlot,
    View,
    ViewResources,
    Container,
    ViewFactory,
    inlineView,
    inject,
    DOM
} from "aurelia-framework";

@customElement("dynamic-html")
@inlineView("<template><div></div></template>")
@inject(DOM.Element, TaskQueue, Container, ViewCompiler)
export class DynamicHtml {
    @bindable()
    public html: string;

    public element: HTMLElement;

    private tq: TaskQueue;
    private container: Container;
    private viewCompiler: ViewCompiler;

    private runtimeView: View;
    private runtimeViewSlot: ViewSlot;
    private runtimeViewFactory: ViewFactory;
    private runtimeViewAnchor: HTMLDivElement;

    constructor(element, tq, container, viewCompiler) {
        this.element = <HTMLElement>element;
        this.tq = tq;
        this.container = container;
        this.viewCompiler = viewCompiler;
    }

    public bindingContext: any;
    public overrideContext: any;
    public bind(bindingContext: any, overrideContext: any): void {
        this.bindingContext = bindingContext;
        this.overrideContext = overrideContext;

        if (this.html) {
            this.htmlChanged(this.html, undefined);
        }
    }

    public unbind(): void {
        this.disposeView();

        this.bindingContext = null;
        this.overrideContext = null;
    }

    public needsApply: boolean = false;
    public isAttached: boolean = false;
    public attached(): void {
        this.runtimeViewAnchor = <HTMLDivElement>this.element.firstElementChild;

        this.isAttached = true;
        if (this.needsApply) {
            this.needsApply = false;
            this.apply();
        }
    }

    public detached(): void {
        this.isAttached = false;

        this.runtimeViewAnchor = null;
    }

    private htmlChanged(newValue: string, oldValue: void): void {
        if (newValue) {
            if (this.isAttached) {
                this.tq.queueMicroTask(() => {
                    this.apply();
                });
            } else {
                this.needsApply = true;
            }
        } else {
            if (this.isApplied) {
                this.disposeView();
            }
        }
    }

    private isApplied: boolean = false;
    private apply(): void {
        if (this.isApplied) {
            this.disposeView();
        }

        this.compileView();
    }

    private disposeView(): void {
        if (this.runtimeViewSlot) {
            this.runtimeViewSlot.unbind();
            this.runtimeViewSlot.detached();
            this.runtimeViewSlot.removeAll();
            this.runtimeViewSlot = null;
        }

        if (this.runtimeViewFactory) {
            this.runtimeViewFactory = null;
        }

        if (this.runtimeView) {
            this.runtimeView = null;
        }

        this.isApplied = false;
    }

    private compileView(): void {
        this.runtimeViewFactory = createViewFactory(this.viewCompiler, this.container, this.html);

        this.runtimeView = createView(this.runtimeViewFactory, this.container);

        this.runtimeViewSlot = createViewSlot(this.runtimeViewAnchor);
        this.runtimeViewSlot.add(this.runtimeView);
        this.runtimeViewSlot.bind(this.bindingContext, this.overrideContext);
        this.runtimeViewSlot.attached();

        this.isApplied = true;
    }

}

function createViewFactory(viewCompiler: ViewCompiler, container: Container, html: string): ViewFactory {
    if (!html.startsWith("<template>")) {
        html = `<template>${html}</template>`;
    }
    let viewResources: ViewResources = container.get(ViewResources);
    let viewFactory = viewCompiler.compile(html, viewResources);
    return viewFactory;
}

function createView(viewFactory: ViewFactory, container: Container): View {
    let childContainer = container.createChild();
    let view = viewFactory.create(childContainer);
    return view;
}

function createViewSlot(containerElement: Element): ViewSlot {
    let viewSlot = new ViewSlot(containerElement, true);
    return viewSlot;
}

这篇关于在aurelia中组成html文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆