Angular组件如何传入包含span/HTML标签的Input属性值
问题原因
Angular 默认开启 XSS 防护,使用插值表达式{{}}渲染变量时,会自动将字符串内的 HTML 标签转义为普通文本,不会解析为真实 DOM 元素,因此直接传入带<span>的字符串无法渲染出预期的标签效果。
实现方案
你可以根据业务场景二选一:
方案1:保留 Input 传参模式,使用 innerHTML 绑定+安全处理
适合 header 内容是动态拼接、后端返回富文本字符串的场景。
- 修改组件 TypeScript 代码,引入 Angular 内置的
DomSanitizer服务,将传入的字符串处理为受信任的安全 HTML,避免 XSS 风险:
import { Component, OnInit, Input, SecurityContext } from '@angular/core'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; @Component({ selector: 'my-component', templateUrl: './my-component.component.html', styleUrls: ['./my-component.component.scss'] }) export class MyComponent implements OnInit { safeHeader: SafeHtml; @Input() set header(val: string) { // 先过滤危险脚本等恶意内容,再标记为可渲染的安全HTML const sanitizedStr = this.sanitizer.sanitize(SecurityContext.HTML, val) || ''; this.safeHeader = this.sanitizer.bypassSecurityTrustHtml(sanitizedStr); } constructor(private sanitizer: DomSanitizer) { } ngOnInit(): void { } }
- 修改组件模板文件,把原来的插值渲染替换为
[innerHTML]属性绑定:
<!-- 原写法会转义HTML:<div class="component-header">{{ header }}</div> --> <div class="component-header" [innerHTML]="safeHeader"></div>
- 处理样式不生效问题:由于动态插入的 HTML 不在 Angular 编译期的模板范围内,默认样式隔离会导致组件内写的标签样式无法命中,需要用
::ng-deep做样式穿透:
// 组件的scss文件 .component-header { // 原有header基础样式 :host ::ng-deep span { color: #2563eb; font-weight: 600; // 其他自定义样式 } }
方案2:使用 Angular 内容投影(更推荐)
适合 header 内容是在业务模板中固定编写的场景,完全规避 XSS 风险,支持在内容里放任意 Angular 组件、指令,扩展性更强。
- 修改组件模板,添加内容投影插槽,不需要保留
header的Input属性:
<div class="component-header"> <!-- 投影插槽,只接收带headerSlot属性的内容 --> <ng-content select="[headerSlot]"></ng-content> </div>
- 业务页面调用组件时,直接把带标签的内容写在组件标签内部,标记到对应插槽即可:
<my-component> <ng-container headerSlot>Hello my <span class="text-highlight">friend</span></ng-container> </my-component>
- 样式可以直接在业务页面的样式文件中给
.text-highlight类编写,不需要做穿透处理,维护更简单。
注意事项
- 禁止跳过
sanitize安全过滤步骤直接调用bypassSecurityTrustHtml,如果传入的内容包含用户可输入的部分,会存在脚本注入的安全风险。 - 两种方案都可以实现需求,动态富文本场景选方案1,固定模板内容场景优先选方案2。
内容的提问来源于stack exchange,提问作者Denver Dang
相关产品推荐
相关产品推荐

