Angular 角度-如何移除<;风格>;来自<;头>;组件销毁后

Angular 角度-如何移除<;风格>;来自<;头>;组件销毁后,angular,Angular,注意:我在Angular 5和Angular 6中都试过这个例子 问题 如果在角度组件上使用“封装:视图封装.无”,则在显示组件时,元素将附加到。元素永远不会被删除,即使在组件被销毁之后也是如此。这就是问题所在。 随着显示的组件越来越多,中的元素也越来越多。根据我的示例,当同一html元素(例如,body)存在全局css规则时,这最终会导致冲突。仅使用最后附加的块中的CSS,即使最后的块属于不再存在的组件 我希望看到一个合适的解决方案,从DOM中删除一些组件附带的元素。例如,当触发组件的onD

注意:我在Angular 5和Angular 6中都试过这个例子

问题 如果在角度组件上使用
“封装:视图封装.无”
,则在显示组件时,
元素将附加到
元素永远不会被删除,即使在组件被销毁之后也是如此。这就是问题所在。 随着显示的组件越来越多,
中的
元素也越来越多。根据我的示例,当同一html元素(例如,
body
)存在全局css规则时,这最终会导致冲突。仅使用最后附加的
块中的CSS,即使最后的
块属于不再存在的组件

我希望看到一个合适的解决方案,从DOM中删除一些组件附带的
元素。例如,当触发组件的
onDestoy
功能时进行清理

我是个新手,我刚刚偶然发现了这种有趣的行为。最好知道是否有一个简单的解决方法


例子 例如:

在我的应用程序中,我有3个包装器组件,它们将成为我的应用程序的根元素。当时只会有一个。显示的组件将决定整个网站的主题。它应该包括全局样式,更具体地说是全局样式(主题)的专用变体。由于这个原因,它们都有
“封装:ViewEncapsulation.None”
。每个全局样式都有自己的编译版本的引导和其他基于SASS变量的外部插件。所以这里没有封装选项,这些是全局样式和插件

只有在显示其他组件并将
元素附加到
之后,解决方案才能第一次正常工作。在此之后,将只使用最后使用的组件中的样式,因为其
位于最后,并覆盖了以前的任何样式


可能的解决方案
似乎唯一的解决方案是重新加载页面,或者不使用组件切换全局主题。

忘记
封装
在您的情况下,它无法帮助您满足您的需求。而是使用一个共享服务,称之为样式服务,它将在文档头中添加/删除样式节点

您不需要在
@组件
装饰器的
样式栏
中添加css样式,而是使用
ngOnInit
函数上的样式服务添加css样式,该功能将样式节点添加到文档头。一旦组件在
ngondestory
函数中被销毁,您将使用样式服务删除样式,该服务将从文档头中删除样式节点

说得够多了,让我们看看一些代码:

style.service.ts

import { Injectable } from '@angular/core';

@Injectable()
export class StyleService {
  private stylesMap: Map<any, Node> = new Map();
  private host: Node;

  constructor() {
    this.host = document.head;
  }

  private createStyleNode(content: string): Node {
    const styleEl = document.createElement('style');
    styleEl.textContent = content;
    return styleEl;
  }

  addStyle(key: any, style: string): void {
    const styleEl = this.createStyleNode(style);
    this.stylesMap.set(key, styleEl);
    this.host.appendChild(styleEl);
  }

  removeStyle(key: any): void {
    const styleEl = this.stylesMap.get(key);
    if (styleEl) {
      this.stylesMap.delete(key);
      this.host.removeChild(styleEl);
    }
  }
}

从StackBlitz样本中提取(分叉)。

如果您投反对票,我也很乐意听到原因。我清楚地描述了这个问题,并设置了live Example您不应该使用加载的组件来编写全局主题。让服务(在应用程序级别)来处理这个问题。如果需要,组件可以通知服务要做什么。因此服务应该编译sass文件并注入全局样式?不,任何组件管理的
body
也会使用服务,但会动态设置样式(通过使用类或直接在模板中或其他方式)。就像任何其他组件样式一样。下面是一个快速拼凑的stackblitz演示:您可以使用
@bespunky/angular zen
中的
头服务来实现这一点:它非常灵活且易于使用。它适用于纯CSS,但是,在使用SASS文件进行样式设置时,有什么解决方案可以奏效吗?@Lars这是个好问题!不幸的是,我不知道这个问题的答案,我必须深入挖掘才能找到答案。如果你能找到答案,如果你能分享,我会很高兴。谢谢
import { Component, OnInit, OnDestroy, Renderer2 } from '@angular/core';

import { StyleService } from '../style.service';

declare const require: any;

@Component({
  selector: 'app-wrapper-variant-red',
  templateUrl: './wrapper-variant-red.component.html',
  styleUrls: [ './wrapper-variant-red.component.css']
})
export class WrapperVariantRedComponent implements OnInit, OnDestroy {

  constructor(private styleService: StyleService) { }

  ngOnInit() {
    this.styleService.addStyle('red-theme', require('../../theme/global-theme-variant-red.css'));
  }

  ngOnDestroy() {
    this.styleService.removeStyle('red-theme');
  }

}