从组件文件和视图模型生成原始HTML字符串

Sha*_*tin 6 javascript typescript aurelia aurelia-binding

我们有这样的模板.

该-template.html

<template><div>${Foo}</div></template>
Run Code Online (Sandbox Code Playgroud)

我们想用它来做这件事.

一些-file.ts

let htmlString = makeItHappen('the-template.html', { Foo = 'bar' });
console.info(htmlString); // <div>bar</div>
Run Code Online (Sandbox Code Playgroud)

什么是我们的makeItHappen功能?

Cha*_*leh 3

好的,要点如下:https://gist.run/? id=d57489d279b69090fb20938bce614d3a

这是以防丢失的代码(带注释):

import {bindable} from 'aurelia-framework';
import {ViewLocator,ViewSlot,ViewEngine,ViewCompileInstruction} from 'aurelia-templating';
import {inject, Container} from 'aurelia-dependency-injection';

@inject(Element,ViewLocator,ViewEngine,Container)
export class LoadViewCustomAttribute {
  @bindable view;
  @bindable viewModel;

  constructor(element,vl,ve,container) {
    this.element = element;
    this.vl = vl;
    this.ve = ve;
    this.container = container;
  }

  attached() {
    // Get a view strategy for this view - this will let Aurelia know how you want to locate and load the view
    var view = this.vl.getViewStrategy(this.view);

    // Create a view factory from the view strategy (this loads the view and compiles it)
    view.loadViewFactory(this.ve, new ViewCompileInstruction()).then(vf => {
      // Create a view from the factory, passing the container (you can create a child container at this point if you want - this is what Aurelia usually does for child views) 
      var result = vf.create(this.container);
      // Bind the view to the VM - I've passed the current VM as the override context which allows Aurelia to do away with the $parent trick 
      result.bind(this.viewModel, this);

      console.log(result); // for inspection

      // Optional - create a viewslot and add the result to the DOM - 
      // at this point you have a view, you can just look at the DOM
      // fragment in the view if you want to pull out the HTML. Bear in 
      // mind, that if you do add to the ViewSlot - since nodes can only 
      // belong to 1 parent, they will be removed from the fragment in 
      // the resulting view (don't let this confuse you when debugging 
      // since Chrome shows a LIVE view of an object if you console.log(it)!) 

      // var vs = new ViewSlot(this.element, true);
      // vs.add(result);

      // Since you can't just get a fragments HTML as a string, you have to
      // create an element, add the fragment and then look at the elements innerHTML...         
      var div = document.createElement('div');
      div.appendChild(result.fragment);
      console.log(div.innerHTML);
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

应该可以做到 - 以及用法:

<template>
  <require from="load-view"></require>
  <section>
    <div load-view="view.bind: 'view-to-load.html'; view-model.bind: { someData: 'test' }"></div>
  </section>
</template>
Run Code Online (Sandbox Code Playgroud)

最后view-to-load.html

<template>
  <div>
    this is the template...  ${someData}
  </div>
</template>
Run Code Online (Sandbox Code Playgroud)

显然,这不一定是自定义属性 - 您只需注入这些位并在辅助类或类似的东西中进行编译(它可以只返回原始 HTML 字符串)。

这将使您的makeItHappen函数相当于attached自定义属性中的方法。当然,您需要所有 deps,因此您至少需要有 Aurelias 依赖注入支持才能掌握这些。

注意:如果您打算将内容添加到 DOM(假设您有一个可以充当锚点的元素),我建议始终使用 ViewSlot,因为这就是 Aurelia 的工作方式,并且它会产生更一致的结果,因为 ViewSlots 知道如何优雅地添加/删除孙子

如果您有一个接受字符串作为模板输入的第 3 方插件,这可能是不可能的 - 但如果可能的话,请寻找与 DOM 节点一起使用的扩展点。