我有一个我依赖的 Angular 组件。该组件有一个getData方法,那么在该组件的模板中调用该方法,并使用Angular插值显示结果。现在我有一个覆盖该方法的子组件。所以我需要从这个子组件返回一个自定义的 html 字符串。
目前我正在将 html 字符串作为输入传递给该组件。但我在用这种方法使用 JavaScript 时遇到了麻烦,而且它不太灵活。
这是代码的简化版本:
@Component({
selector: 'app-parent',
template: "
<div>
Parent Component:
<div>{{ getData() }}</div>
</div>
"
})
export class ParentComponent {
getData(): string {
return ''; // This will be overridden by the child component
}
}
@Component({
template: '',
})
export class ChildComponent extends ParentComponent {
getData(): string {
return '<h2>My Title</h2>'; // Custom HTML string
}
}
我可以输入代码吗
<h2>My Title</h2>
进入自定义组件并返回该组件而不是返回 html 字符串。请注意,我无法更改 ParentComponent 的工作方式。
在 Angular 中,插值 ({{ }}) 用于将组件类属性绑定到组件模板中的文本节点。这意味着您不能直接使用插值来插入或渲染 HTML 元素或 Angular 组件。插值将任何值视为字符串,因此如果您尝试将 HTML 或组件选择器作为字符串返回,Angular 会将其转义以防止 XSS(跨站脚本)等安全问题,并且它将在 DOM 中呈现为纯文本.
鉴于您所描述的约束,您无法更改 ParentComponent 实现,但希望从 ChildComponent 返回自定义 HTML 或 Angular 组件,您将面临限制,因为 Angular 不支持直接通过渲染组件或 HTML以这种方式插值。
但是,还有其他方法可以在 Angular 应用程序中动态渲染组件或 HTML,尽管它们可能不适用于无法更改 ParentComponent 的特定约束。其中包括:
使用 Angular 的 DomSanitizer 进行安全 HTML 绑定: 如果您只需要插入 HTML(而不是 Angular 组件),则可以使用 Angular 的 [innerHTML] 绑定来安全地插入 HTML 内容。您需要使用 Angular 的 DomSanitizer 清理 HTML 内容以绕过安全检查。这并不直接适用于您的场景,因为ParentComponent的模板无法更改。
动态组件加载: Angular 提供了使用 ViewContainerRef 和 ComponentFactoryResolver 在运行时动态加载组件的机制。这种方法允许更复杂的组件插入场景,但需要占位符指令或父组件模板中的已知插入点,这在您的情况下似乎不是一个选项。
考虑到您的限制,Angular 的设计不支持您正在寻求的最直接的方法(直接从方法返回组件并通过插值渲染它)。
一个潜在的解决方法虽然并不理想,并且取决于您的完整应用程序上下文,但可能是重新评估解决方案的架构。考虑是否:
如果涉及数据获取或处理,getData() 中的逻辑可以移动到服务中,从而允许不同的组件以独特的方式对此数据做出反应。 子组件可以使用 ng-content 或模板出口将内容投影到父组件中,尽管这需要更改父组件的结构。 在您被锁定到特定架构而无法更改父组件的情况下,最好的行动方案可能是重新考虑组件之间的交互模式,或者诉诸于在 Angular 上下文之外使用本机 JavaScript 解决方案,这来自有其自身的一系列挑战,通常不推荐。
动态 HTML 内容指令 下面介绍了如何设置指令来动态插入 HTML。这假设您有某种方法可以在模板中的所需位置应用此指令。
// dynamic-html.directive.ts
import { Directive, Input, ElementRef, OnInit, Renderer2, SecurityContext } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
@Directive({
selector: '[appDynamicHtml]'
})
export class DynamicHtmlDirective implements OnInit {
@Input() appDynamicHtml: string;
constructor(private elementRef: ElementRef, private renderer: Renderer2, private sanitizer: DomSanitizer) {}
ngOnInit(): void {
const sanitizedHtml = this.sanitizer.sanitize(SecurityContext.HTML, this.appDynamicHtml);
if (sanitizedHtml) {
this.renderer.setProperty(this.elementRef.nativeElement, 'innerHTML', sanitizedHtml);
}
}
}
应用指令 假设您可以向 ParentComponent 的模板添加指令(您提到的不可能),则该指令将按如下方式使用:
<!-- In parent or child component template -->
<div appDynamicHtml="{{ getData() }}"></div>