【发布时间】:2016-09-16 09:59:07
【问题描述】:
我对 Angular 还是很陌生,并且遇到了以下问题。
我想在 DOM 中呈现我的组件模板的内容。目标是生成一个样式指南,我想在其中显示模板的 code-sn-ps。因此我需要转义的模板内容。
我已经尝试了几件事,并想出了一个可能的解决方案来创建一个自定义渲染器,它可以逃避模板输出。
我认为它可以像这里描述的那样简单:Rendering in Angular 但是……不是。
我按照此处Stack Overflow - custom-renderer-for-angular2 的描述创建了一个自定义渲染器,它首先应该像默认的DebugDomRenderer 一样工作。但是我不知道如何使用这个渲染器。
我尝试过这样的事情:
import {Component} from '@angular/core';
import {EscapeRootRenderer} from "../../renderer/escapeRootRenderer";
import {DebugDomRootRenderer} from "@angular/core/src/debug/debug_renderer";
@Component({
selector:'escape',
template:'<pre><code><ng-content></ng-content></code></pre>',
providers:[
{provide: DebugDomRootRenderer, useClass:EscapeRootRenderer}
]
})
export class EscapeComponent{
}
这部分还没有准备好。我的计划是采用 ChildViews 并使其逃脱......
我的 EscapeRootRender 和 DebugDomRootRenderer 做的事情完全一样,只是我删除了调试内容并添加了一些 console.logs()
import {Injectable, RenderComponentType, Renderer, RootRenderer} from '@angular/core';
import {AnimationStyles} from "@angular/core/esm/src/animation/animation_styles";
import {AnimationKeyframe} from "@angular/core/esm/src/animation/animation_keyframe";
@Injectable()
export class EscapeRootRenderer implements RootRenderer {
constructor(private _delegate:RootRenderer) {
console.log('EscapeRootRenderer constructed')
console.log(_delegate)
}
renderComponent(componentProto: RenderComponentType): EscapeRenderer {
console.log('EscapeRootRenderer - renderComponent');
return new EscapeRenderer(this._delegate.renderComponent(componentProto));
}
}
export class EscapeRenderer implements Renderer{
constructor( private _delegate: Renderer){
console.log('EscapeRenderer constructed');
}
animate(element: any, startingStyles: AnimationStyles, keyframes: AnimationKeyframe[], duration: number, delay: number, easing: string): any {
console.log('EscapeRenderer animate');
return this._delegate.animate(element, startingStyles, keyframes, duration, delay, easing);
}
selectRootElement(selector: string): any {
console.log('EscapeRenderer selectRootElement');
var nativeEl = this._delegate.selectRootElement(selector);
return nativeEl;
}
createElement(parentElement: any, name: string): any {
console.log('EscapeRenderer createElement');
var nativeEl = this._delegate.createElement(parentElement, name);
return nativeEl;
}
createViewRoot(hostElement: any): any {
console.log('EscapeRenderer createViewRoot');
return this._delegate.createViewRoot(hostElement); }
createTemplateAnchor(parentElement: any): any {
console.log('EscapeRenderer createTemplateAnchor');
var comment = this._delegate.createTemplateAnchor(parentElement);
return comment;
}
createText(parentElement: any, value: string): any {
console.log('EscapeRenderer createText');
var text = this._delegate.createText(parentElement, value);
return text;
}
projectNodes(parentElement: any, nodes: any[]) {
console.log('EscapeRenderer projectNodes');
return this._delegate.projectNodes(parentElement, nodes);
}
attachViewAfter(node: any, viewRootNodes: any[]) {
console.log('EscapeRenderer attachViewAfter');
return this._delegate.attachViewAfter(node, viewRootNodes);
}
detachView(viewRootNodes: any[]) {
console.log('EscapeRenderer detachView');
return this._delegate.detachView(viewRootNodes);
}
destroyView(hostElement: any, viewAllNodes: any[]) {
console.log('EscapeRenderer destroyView');
return this._delegate.destroyView(hostElement, viewAllNodes);
}
listen(renderElement: any, name: string, callback: Function) {
console.log('EscapeRenderer listen');
return this._delegate.listen(renderElement, name, callback);
}
listenGlobal(target: string, name: string, callback: Function): Function {
console.log('EscapeRenderer listenGlobal');
return this._delegate.listenGlobal(target, name, callback);
}
setElementProperty(renderElement: any, propertyName: string, propertyValue: any) {
console.log('EscapeRenderer setElementProperty');
return this._delegate.setElementProperty(renderElement, propertyName, propertyValue);
}
setElementAttribute(renderElement: any, attributeName: string, attributeValue: string) {
console.log('EscapeRenderer setElementAttribute');
return this._delegate.setElementAttribute(renderElement, attributeName, attributeValue);
}
/**
* Used only in debug mode to serialize property changes to comment nodes,
* such as <template> placeholders.
*/
setBindingDebugInfo(renderElement: any, propertyName: string, propertyValue: string) {
console.log('EscapeRenderer setBindingDebugInfo');
return this._delegate.setBindingDebugInfo(renderElement, propertyName, propertyValue);
}
setElementClass(renderElement: any, className: string, isAdd: boolean) {
console.log('EscapeRenderer setElementClass');
return this._delegate.setElementClass(renderElement, className, isAdd);
}
setElementStyle(renderElement: any, styleName: string, styleValue: string) {
console.log('EscapeRenderer setElementStyle');
return this._delegate.setElementStyle(renderElement, styleName, styleValue);
}
invokeElementMethod(renderElement: any, methodName: string, args: any[]) {
console.log('EscapeRenderer invokeElementMethod');
return this._delegate.invokeElementMethod(renderElement, methodName, args);
}
setText(renderNode: any, text: string) {
console.log('EscapeRenderer setText');
return this._delegate.setText(renderNode, text); }
}
现在问题:
- 这是(customRenderer)处理模板内容转义问题的一种方法,还是我完全错了?
- 如何告诉单个组件使用不同的渲染器?
感谢您的帮助,
最佳一月
【问题讨论】:
-
我认为需要在全球范围内提供渲染器,而不是每个组件(我自己还没有尝试过)。
-
我也试过了:providers:[ {provide:DebugDomRootRenderer, useClass:EscapeRootRenderer} ]
-
你真的想要渲染组件的视图源代码,还是想要渲染包含 Angular2 绑定但阻止 Angular2 处理绑定的 HTML?如果您使用 AoT,组件将不会包含原始视图代码。然后用 JS 代码替换绑定。
-
我想渲染转义的模板文件 -->
<div class="component"><div class="component__element"></div></div>在网站上查看真正的 HTML 代码。开发人员无需打开开发工具即可复制的代码片段......我已经做到了,但是以一种非常简单的方式,请参阅答案 -
Somebody here on stackblitz 实现了一个完整的渲染器(遍历节点,通过命令添加类......)