【问题标题】:How to use Custom Renderer in Angular2如何在 Angular2 中使用自定义渲染器
【发布时间】: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); }

}

现在问题:

  1. 这是(customRenderer)处理模板内容转义问题的一种方法,还是我完全错了?
  2. 如何告诉单个组件使用不同的渲染器?

感谢您的帮助,

最佳一月

【问题讨论】:

  • 我认为需要在全球范围内提供渲染器,而不是每个组件(我自己还没有尝试过)。
  • 我也试过了:providers:[ {provide:DebugDomRootRenderer, useClass:EscapeRootRenderer} ]
  • 你真的想要渲染组件的视图源代码,还是想要渲染包含 Angular2 绑定但阻止 Angular2 处理绑定的 HTML?如果您使用 AoT,组件将不会包含原始视图代码。然后用 JS 代码替换绑定。
  • 我想渲染转义的模板文件 --> &lt;div class="component"&gt;&lt;div class="component__element"&gt;&lt;/div&gt;&lt;/div&gt;在网站上查看真正的 HTML 代码。开发人员无需打开开发工具即可复制的代码片段......我已经做到了,但是以一种非常简单的方式,请参阅答案
  • Somebody here on stackblitz 实现了一个完整的渲染器(遍历节点,通过命令添加类......)

标签: angularjs angular


【解决方案1】:

我在没有任何自定义渲染器的情况下解决了我的问题:

import {
  Component, ViewChild, OnInit, AfterViewInit, OnInit
} from '@angular/core';


@Component({
  selector:'escape',
  template:'<content #kiddo><ng-content></ng-content></content><pre><code #codeContent>{{componentInnerHTML}}</code></pre>'
})

export class EscapeComponent implements OnInit, AfterViewInit{
  @ViewChild('kiddo') viewChild;
  @ViewChild('codeContent') codeContent;
  componentInnerHTML:string;

  ngAfterViewInit(){
    this.componentInnerHTML = this.viewChild.nativeElement.innerHTML;
  }

  ngOnInit(){
    var that = this;
    setTimeout(()=>hljs.highlightBlock(that.codeContent.nativeElement), 1)
  }
}

结果现在看起来像这样。开发者现在可以直接从网站上直接复制代码...

Screenshot output EscapeComponent

但是,我仍然对如何使用自定义渲染器感兴趣。

【讨论】:

    【解决方案2】:

    我仍然不完全理解这个问题,但也许这就是你想要的

    <pre ngNonBindable>
        template content here
    </pre>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-13
      • 2019-01-31
      • 2020-10-28
      • 2018-07-26
      • 2018-01-21
      • 2017-06-09
      • 2019-11-02
      相关资源
      最近更新 更多