2016-10-12 2 views
1

Я хотел бы, чтобы достичь чего-то подобного, как «включить» в андроиде, но в Aurelia:сочинял HTML файл в Aurelia

Как придать простое содержимое файла HTML в мою точке зрения, с зыванием оценивали в пределах родительского вида, и без использования пользовательского элемента? Связывание innerhtml недостаточно, поскольку, согласно документу, выражения привязок обходят.

+1

Вы можете использовать элемент compose для этого, но я должен спросить, почему вы не хотели бы использовать только пользовательский элемент html? –

+0

Из-за проблем с проверкой и пользовательскими элементами. Спасибо «" работает. – Benoit

+1

'compose' - это собственный пользовательский элемент. Если он работает с 'compose', то он будет работать с настраиваемым элементом, который вы создаете самостоятельно. Вот исходный код 'compose': https://github.com/aurelia/templating-resources/blob/master/src/compose.js#L12 Я постоянно отталкиваю людей от использования' compose', потому что пользовательские элементы, которые вы создаете вы почти всегда будете быстрее, чем динамическая настройка 'compose'. –

ответ

2

Как уже сказал Эшли, элемент <compose view="./your-view.html"></compose> будет работать с существующим HTML-файлом, и он наследует родительский контекст.

Если вы хотите, чтобы составить HTML динамически (из файла, базы данных, или застроенных программно), а затем с помощью ViewCompiler даст вам лучшую производительность и гибкость, так как это один слой меньше compose по сравнению с тем, как Aurelia строит пользовательские элементы внутри.

Я дал аналогичный ответ на другой (но соответствующий) вопрос здесь:

Aurelia dynamic binding

Вы хотите использовать text плагин для загрузки файла HTML как текст в переменную, а затем передать, что к ViewCompiler. У меня есть пользовательский элемент для этого, который с точки зрения производительности, вероятно, не лучше, чем compose, но он позволяет больше контролировать работу с сырым html в качестве входных данных, и вы можете сделать свою собственную оптимизацию производительности, соответствующую вашей ситуации по мере необходимости:

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 в:

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; 
} 
Смежные вопросы