在 Angular 15 中渲染 HTML

问题描述 投票:0回答:1

在 Angular 15.2 中,我尝试创建一个组件,该组件将包含有效 HTML 的字符串作为输入并呈现此 HTML。 第一次尝试是尝试使用 ElementRef 和innerHTML,如下所示:

constructor(
  private readonly componentElement: ElementRef,
) {}

ngOnInit(): void {
  (this.componentElement.nativeElement as HTMLElement).innerHTML = html;
}

这将呈现消息

SafeValue must use [property]=binding:
以及
html
变量中包含的一些 HTML。

所以我尝试使用 DomSanitizer 来解决这个问题:

constructor(
  private readonly sanitizer: DomSanitizer,
  private readonly componentElement: ElementRef,
) {}

ngOnInit(): void {
  const safer = this.sanitizer.bypassSecurityTrustHtml(html);
  (this.componentElement.nativeElement as HTMLElement).innerHTML = safer;
}

这会生成错误:

Type 'SafeHtml' is not assignable to type 'string'

所以我改变了我的方法,使用

Renderer2

constructor(
  private readonly sanitizer: DomSanitizer,
  private readonly componentElement: ElementRef,
) {}

ngOnInit(): void {
  const safer = this.sanitizer.bypassSecurityTrustHtml(html);
  this.renderer.setProperty(this.componentElement.nativeElement, 'innerHTML', safer)
}

这将再次呈现消息

SafeValue must use [property]=binding:
以及 html 变量中包含的一些 HTML。

我就是无法让它工作! 我这样做是为了避免在 dom 上打印一个 HTML 包装元素,其中包含属性

[innerHTML]
。所以我不接受那些建议用包装器等不必要的元素弄脏 DOM 的答案。

angular
1个回答
0
投票

您遇到的错误消息是因为 Angular 旨在防止将潜在不安全的值直接分配给某些属性(例如

innerHTML
),以减轻跨站点脚本 (XSS) 攻击等安全风险。

要在 Angular 中动态渲染 HTML,同时保持安全性,您可以使用 Angular 的内置

DomSanitizer
以及属性绑定或指令。以下是实现它的方法:

  1. 使用属性绑定: 在您的组件模板中,将

    innerHTML
    属性绑定到保存已清理 HTML 的变量。

    <div [innerHTML]="sanitizedHtml"></div>
    

    在您的组件类中,使用

    DomSanitizer
    :

    清理 HTML
    import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
    
    constructor(private sanitizer: DomSanitizer) {}
    
    ngOnInit(): void {
      const html = '<p>This is some <strong>HTML</strong> content.</p>';
      this.sanitizedHtml = this.sanitizer.bypassSecurityTrustHtml(html);
    }
    
  2. 使用指令: 您可以创建自定义指令来动态呈现 HTML。

    import { Directive, ElementRef, Input, OnInit } from '@angular/core';
    import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
    
    @Directive({
      selector: '[appRenderHtml]'
    })
    export class RenderHtmlDirective implements OnInit {
      @Input('appRenderHtml') html: string;
    
      constructor(private el: ElementRef, private sanitizer: DomSanitizer) {}
    
      ngOnInit(): void {
        const sanitizedHtml: SafeHtml = this.sanitizer.bypassSecurityTrustHtml(this.html);
        this.el.nativeElement.innerHTML = sanitizedHtml.toString();
      }
    }
    

    然后,您可以在组件的模板中使用此指令

    <div [appRenderHtml]="html"></div>
    

    在你的组件类中

    export class YourComponent {
      html: string = '<p>This is some <strong>HTML</strong> content.</p>';
    }
    

这两种方法都通过在渲染 HTML 之前对其进行清理来利用 Angular 的安全功能。选择更适合您的要求和编码风格的一种。

© www.soinside.com 2019 - 2024. All rights reserved.