2017-08-04 93 views
1

我正在尝试创建一个共享Angular组件的库,以便用于多个不同的Web项目。随着共享组件库,我试图创建一个Web项目,其中包含并显示所有这些组件和代码示例以了解如何使用它们。有没有办法获取Angular *组件的HTML模板?

如从有关的类似问题的其他查询看出,为了在网页中在<pre><code>标签显示HTML代码,这些HTML片段的某些方面需要有HTML编码的字符(即>需要是&gt;<需要是&lt;)。手动从源代码进行这些更改的需求可能非常繁琐和繁琐。

我想找到一种方法来读取给定组件的HTML模板,使少量文本替换所需,然后将该值设置为要显示在视图中的属性。我见过其他类似的SO问题,如this

如果我有foo.component.ts如下:

import { Component } from '@angular/core'; 

@Component({ 
    selector: 'foo', 
    template: ` 
     <div class="foo"> 
      <div class="content"> 
       <ng-content select="[top-content]"></ng-content> 
      </div> 
      <div class="extra content"> 
       <ng-content select="[bottom-content]"></ng-content> 
      </div> 
     </div> 
    ` 
}) 
export class FooComponent {} 

我想创建一个display-foo.component.ts的东西如下:

import { Component } from '@angular/core'; 
import { FooComponent } from './foo.component'; 

@Component({ 
    selector: 'display-foo', 
    template: ` 
     <pre class="example-code"> 
      <code> 
      {{encodedExampleHtml}} 
      </code> 
     </pre> 
     <foo> 
      <div top-content>TOP</div> 
      <div bottom-content>BOTTOM</div> 
     </foo> 
    ` 
}) 
export class DisplayFooComponent { 
    encodedExampleHtml: string; 

    constructor() { 
    this.encodedExampleHtml = new FooComponent().template.replace('<', '&lt;').replace('>', '&gt;'); 
    } 
} 

在本质上,这将使该模板在UI下一个开发商查看并理解如何利用以及该类型组件的实际渲染元素以及显示组件在实际应用程序中使用时的外观。

DisplayFooComponent我无法弄清楚如何工作的部分是这一行this.encodedExampleHtml = new FooComponent().template.replace('<', '&lt;').replace('>', '&gt;');把它当作我想做的事情的伪代码,因为Angular组件对象没有模板属性,而且据我所见没有显示该组件的模板的属性。

有没有一种方法可以利用Angular框架获取组件的HTML模板?同样,我不希望带有表达式的内插内容被替换,而是由装饰器的template属性或其templateUrl属性与元素相关联的实际原始HTML模板?

+0

你打算使用AOT吗? – yurzui

+0

@yurzui是的,我正在计划它 – peinearydevelopment

回答

3

您可以尝试使用特殊功能来获得注释:

注解。TS

declare let Reflect: any; 
export function getAnnotation(typeOrFunc: Type<any>): any[]|null { 
    // Prefer the direct API. 
    if ((<any>typeOrFunc).annotations) { 
    let annotations = (<any>typeOrFunc).annotations; 
    if (typeof annotations === 'function' && annotations.annotations) { 
     annotations = annotations.annotations; 
    } 
    return annotations[0]; 
    } 

    // API of tsickle for lowering decorators to properties on the class. 
    if ((<any>typeOrFunc).decorators) { 
    return convertTsickleDecoratorIntoMetadata((<any>typeOrFunc).decorators)[0]; 
    } 

    // API for metadata created by invoking the decorators. 
    if (Reflect && Reflect.getOwnMetadata) { 
    return Reflect.getOwnMetadata('annotations', typeOrFunc)[0]; 
    } 
    return null; 
} 

function convertTsickleDecoratorIntoMetadata(decoratorInvocations: any[]): any[] { 
    if (!decoratorInvocations) { 
    return []; 
    } 
    return decoratorInvocations.map(decoratorInvocation => { 
    const decoratorType = decoratorInvocation.type; 
    const annotationCls = decoratorType.annotationCls; 
    const annotationArgs = decoratorInvocation.args ? decoratorInvocation.args : []; 
    return new annotationCls(...annotationArgs); 
    }); 
} 

然后

this.encodedExampleHtml = getAnnotation(FooComponent).template; 

Plunker Example

参见

+0

啊,熟悉的事情) –

+0

@Maximus是啊,你是。这里没有新东西。这是基本的水平 – yurzui

+0

这似乎不是角度特定的,而是从任何装饰者获取任何信息的方式。有没有任何角度特定的机制? – peinearydevelopment

0

yurzui's answer工作正常角4.4.2而不是5.0.2。注释机制已更改:使用属性而不是Reflect.defineMetadata()来存储元数据。因为它没有记录,人们只能在代码中找到它:

const /** @type {?} */ TypeDecorator = (function TypeDecorator(cls) { 
    const /** @type {?} */ annotations = Reflect.getOwnMetadata('annotations', cls) || []; 
    annotations.push(annotationInstance); 
    Reflect.defineMetadata('annotations', annotations, cls); 
    return cls; 
}); 
在角4.4.2

@angular/core/@angular/core.js,l.356),以

const ANNOTATIONS = '__annotations__'; 
const /** @type {?} */ TypeDecorator = /** @type {?} */ (function TypeDecorator(cls) { 
    // Use of Object.defineProperty is important since it creates non-enumerable property which 
    // prevents the property is copied during subclassing. 
    const /** @type {?} */ annotations = cls.hasOwnProperty(ANNOTATIONS) ? 
     (/** @type {?} */ (cls))[ANNOTATIONS] : 
     Object.defineProperty(cls, ANNOTATIONS, { value: [] })[ANNOTATIONS]; 
    annotations.push(annotationInstance); 
    return cls; 
}); 
在角5.0.2

@angular/core/esm2015/core.js,L 0.96)。

访问元数据的更新代码,例如模板:

import 'reflect-metadata'; 

export function getAnnotation(typeOrFunc: Type<any>): any[]|null { 
    // Prefer the direct API. 
    if ((<any>typeOrFunc)['__annotations__']) { 
     return (<any>typeOrFunc)['__annotations__'][0]; 
    } 

    // API of tsickle for lowering decorators to properties on the class. 
    if ((<any>typeOrFunc).decorators) { 
    return convertTsickleDecoratorIntoMetadata((<any>typeOrFunc).decorators)[0]; 
    } 

    // API for metadata created by invoking the decorators. 
    if (Reflect && Reflect.getOwnMetadata) { 
    return Reflect.getOwnMetadata('annotations', typeOrFunc)[0]; 
    } 
    return null; 
} 

function convertTsickleDecoratorIntoMetadata(decoratorInvocations: any[]): any[] { 
    if (!decoratorInvocations) { 
    return []; 
    } 
    return decoratorInvocations.map(decoratorInvocation => { 
    const decoratorType = decoratorInvocation.type; 
    const annotationCls = decoratorType.annotationCls; 
    const annotationArgs = decoratorInvocation.args ? decoratorInvocation.args : []; 
    return new annotationCls(...annotationArgs); 
    }); 
} 
相关问题