【问题标题】:Prevent child component <style> added with innerHtml to be applied to parent防止使用 innerHtml 添加的子组件 <style> 应用于父组件
【发布时间】:2018-07-05 22:41:21
【问题描述】:

如何防止使用innerHtml 添加到子组件的子组件样式应用于父组件?巧合的是,父级可能已经有一个同名的 css 类。如果 ViewEncapsulation 设置为 Native,这似乎可以正常工作(孩子有红色背景,父母有绿色),但使用 Emulated 它不会。我不能用Native,据说不是所有浏览器都支持。

app.ts

import {Component, NgModule, VERSION} from '@angular/core'
import {BrowserModule, DomSanitizer} from '@angular/platform-browser'
import {Component, Input, ViewEncapsulation} from '@angular/core'

@Component({
  selector: 'my-app',
  template: `<div class="header">
    <h2>Hello {{name}}</h2>
</div>
<hr>
  <child [content]="content"></child>
`,

})

export class App {
  name:string;
  content:string = '<style>.header {background-color:red;color:white;}</style><div class="header">This is child content</div>'
  constructor(public ds: DomSanitizer) {
    this.content = this.ds.bypassSecurityTrustHtml(this.content);
    this.name = `Angular! v${VERSION.full}`
  }
}

@Component({
  selector: 'child',
  template:`<div [innerHtml]="content"></div>`,
  encapsulation:ViewEncapsulation.Emulated
//  encapsulation:ViewEncapsulation.Native
})
export class child{
 @Input('content') content;

}

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App, child ],
  bootstrap: [ App ]
})
export class AppModule {}

style.css

.header {
      background-color:green;
      color:white;
} 

Plunker example

【问题讨论】:

  • 原生模式在 Firefox 中不起作用,但在 Chrome 中起作用

标签: angular innerhtml


【解决方案1】:

任何组件都应该有自己的样式表。在那里你可以添加这样的东西:

:host {
  //styling
}
:host > div { //etc }

任何带有 :host 的东西都适用于该组件。这不能解决您的问题吗?

例如,如果您知道要添加什么结构,则可以将其写入组件装饰器:

@Component({
  selector: 'child',
  template: `<div [innerHtml]="content"></div>`,
  encapsulation: ViewEncapsulation.Emulated,
  styles: [ ':host { position: absolute; top: 10%; }' ]
})

然后您仍然可以添加您的 innerHtml 并且样式将应用于它。因此,在上述情况下,当组件部署在 DOM 中时,应将 :host {} 样式应用于组件。从那时起,如果您知道您的 innerHtml 将包含哪些结构/标签/类,那么只需为它们设置样式即可。

或者。而不是像上面这样的样式,将其更改为它自己的样式表:

  styleUrls: ['/some/path/to/stylesheet.css']

【讨论】:

  • 子组件从字符串获取它的样式,而不是从样式元标记。请解释注入样式如何仅应用于儿童。此示例仅为演示而缩小
  • 你不能给它自己的样式表吗?毕竟它确实解决了您的问题。
  • 我不明白你的意思,我应该给它自己的样式表吗?如果是,我如何进行角度渲染并将其应用于子 innerHtml?
  • 更新了答案,以样式和 styleUrls 为例。
  • 我不知道会在孩子的innerHtml中添加什么css或html,它只需要与父母隔离。 :host 可以以某种方式添加到未知的 css 并由 angular 编译吗?不能使用 styleurls 作为 css 和 html 在字符串中接收
【解决方案2】:

我的发现:(Angular 5)Emulate 封装不起作用,因为它只在编译时应用,Native 是在运行时应用,但它不能使用,因为它不支持跨浏览器。由于 Angular 在运行时不控制 innerHtml,因此 html 直接插入到 dom 中,这可能导致具有现有名称的类无意中被插入的 html/css 覆盖。 因此,目前,避免此问题的唯一解决方案是在将其插入 dom 之前手动重命名 css 类及其在 html 中的引用。当 :host 在样式装饰器中指定时,这就是 Angular 隔离 css 的作用。目前也没有办法在运行时触发 angular 对自定义 css/html 字符串的编译,这将为我们重命名,尽管功能显然存在。

【讨论】:

    猜你喜欢
    • 2021-06-11
    • 2017-07-10
    • 2018-04-29
    • 1970-01-01
    • 2019-09-08
    • 2013-06-11
    • 2020-06-02
    • 2021-01-18
    • 1970-01-01
    相关资源
    最近更新 更多