gpt4 book ai didi

angular - 为 Angular 添加到 DOM 的每个 HTML 元素添加一个 CSS 类

转载 作者:太空狗 更新时间:2023-10-29 18:30:30 25 4
gpt4 key购买 nike

有没有一种方法可以将 CSS 类(例如 .angular-app)添加到 Angular(如 Angular 4)添加到 DOM 的每个单个 HTML 元素?我所说的“每一个 HTML 元素”还指模板中的子元素和孙子元素以及嵌入的内容,即不仅仅是 Angular 组件/指令/主机。

背景:我正在处理一个包含数十万行代码(包括数万行 CSS)的大型单体 AngularJS 项目。现在,该项目的一些 AngularJS 组件应该是 upgraded到 Angular 。不幸的是,AngularJS 项目周围的许多样式都泄漏到 Angular 组件中,并与我们想要在那里使用的样式发生冲突。因此,我们正在考虑的一种解决方案是向 AngularJS 样式的每个选择器添加一个 :not(.angular-app) 选择器(通过 SASS 或一些后处理 Python 脚本),以便它们不匹配 Angular 组件中使用的任何元素。

有什么办法可以解决这个问题吗?

旁注:显然,这个问题可以通过在 Angular 组件的 CSS 中使用 all: revert 或通过创建 ShadowDOM 轻松解决,但由于这些技术几乎不受支持浏览器,我们需要一个中间解决方案。 (为了完整起见,另一种解决方案是向 AngularJS 样式表的每个选择器添加一个 :not() 选择器,以确保我们不在 Angular 组件内,而是在 this would require CSS 4 selectors 内。)

[编辑]:我想这可以通过为 Angular 组件编写自定义渲染器来完成(请参阅 these links ),但我不完全确定如何实现。例如createElementappendElement 由 Angular 本身用于它处理的每个 HTML 元素?

最佳答案

您链接的文章有点过时,实现方式也略有变化。

如果您想实现 Renderer2 的完全任意实现,可以通过使用返回自定义渲染器的 createRenderer 方法简单地实现 RendererFactory2 来实现。

export class MyRenderer implements Renderer2 {
createElement(name: string, namespace?: string) {
const el = document.createElement(name);
el.setAttribute(name, 'marking Angular component');
return el;
}
...


export class MyRendererFactory implements RendererFactory2 {
createRenderer(hostElement): Renderer2 {
return new MyRenderer();
}
...

@NgModule({
providers: [ { provide: RendererFactory2, useClass: MyRendererFactory } ],
...
})
export class AppModule { }

See demo here .

但是,如果您想扩展默认功能,Angular 现在似乎不支持它。 RendererFactory2 的默认实现是 DomRendererFactory2,它根据封装模式返回 3 种不同的渲染器:

export class DomRendererFactory2 implements RendererFactory2 {
createRenderer(element: any, type: RendererType2|null): Renderer2 {
switch (type.encapsulation) {
case ViewEncapsulation.Emulated: {
return new EmulatedEncapsulationDomRenderer2(this.eventManager, this.sharedStylesHost, type);;
}
case ViewEncapsulation.Native:
return new ShadowDomRenderer(this.eventManager, this.sharedStylesHost, element, type);
default: {
return new DefaultDomRenderer2(eventManager);
}
}
}

不幸的是,这些类都不是

DomRendererFactory2 
DefaultDomRenderer2
EmulatedEncapsulationDomRenderer2
ShadowDomRenderer

可作为公共(public) API 使用。

如果您计划单独使用 ViewEncapsulation.Native,您可以在 DomRendererFactory2defaultRenderer 属性中访问 DefaultDomRenderer2 > 在工厂启动时创建:

@Injectable()
export class DomRendererFactory2 implements RendererFactory2 {
private defaultRenderer: Renderer2;

constructor(private eventManager: EventManager, private sharedStylesHost: DomSharedStylesHost) {
this.defaultRenderer = new DefaultDomRenderer2(eventManager);
}

然后装饰它的createElement方法:

@NgModule({
imports: [BrowserModule],
declarations: [AppComponent, AComponent, ADirective],
bootstrap: [AppComponent]
})
export class AppModule {
constructor(factory: RendererFactory2) {
const createElement = Object.getPrototypeOf(factory.defaultRenderer).createElement;

Object.getPrototypeOf(factory.defaultRenderer).createElement = function (...args) {
const el = createElement(...args);
el.setAttribute(name, 'marking Angular component');
return el;
}
}
}

Here is the demo .

但是,该属性是私有(private)的。

您还可以使用提供自定义 Renderer 的第一种方法,并简单地从源代码中复制所有实现。

任何解决方案似乎仍然存在风险。

关于angular - 为 Angular 添加到 DOM 的每个 HTML 元素添加一个 CSS 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46650814/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com