繁体   English   中英

Angular:如何添加全局 CSS(例如添加到正文),但仅针对一个特定页面?

[英]Angular: How to add global CSS (e.g. to the body), but only for one specific page?

我怎样才能在角添加单独的CSS一个页面?

这是我需要的 CSS,根据如何从打印页面中删除 URL?

@media print{
    @page{
        margin:0;
    }
    body{
        margin:30px;
    }
}

但是使用::ng-deepViewEncapsulation.None将 CSS 放入组件在这里ViewEncapsulation.None ,因为当导航离开页面时,页面的 CSS 不会被删除。

我添加了一个Stackblitz ,它清楚地解释了这个问题。


我想出了一个潜在的解决方案,但它不起作用:

  encapsulation: ViewEncapsulation.None

   ...      

  constructor(private renderer: Renderer2) {
    this.renderer.addClass(document.body, 'special-print');
   }

  ngOnDestroy() {
    this.renderer.removeClass(document.body, 'special-print');
  }
  ....
  ....
  ....
  @media print{
    @page{
        margin:0;
    }
    body.special-print{
        margin:30px;
    }
  }

为什么它不起作用:

虽然它对<body> CSS 有帮助,但@page CSS 没有帮助。 也许这个问题可以更好地概括为“如何添加全局 CSS,但在我们离开页面时将其删除?”。

解决了!

我们将<style>块直接打印到组件的 HTML 中,因此当组件被移除时,我们的<style>块也会被移除。 通常这行不通,但多亏了DomSanitizer.bypassSecurityTrustHtml ,Angular 在运行优化时不会破坏我们的代码。)

这是一个StackBlitz

首先,创建一个新组件来处理工作:

component.ts: (This is all we need. We don't need an HTML or style.css file.)
//Inside  your local component, place this HTML 
//<app-local-css [style]="'body{background:green !important;}'"></app-local-css>
// OR
//<app-local-css [scriptURL]="'/path/to/file.css'"></app-local-css>

@Component({
  selector: "app-local-css",
  template: '<span style="display:none" [innerHTML]="this.safeString"></span>'
})
export class LocalCSSComponent implements OnInit {
  constructor(protected sanitizer: DomSanitizer) {}
  @Input() scriptURL?: string;
  @Input() style?: string;

  safeString: SafeHtml;
  ngOnInit() {
    if (this.scriptURL) {
      let string = '<link rel="stylesheet" type="text/css" href="' + this.scriptURL + '">';
      this.safeString = this.sanitizer.bypassSecurityTrustHtml(string);
    } else if (this.style) {
      let string = '<style type="text/css">' + this.style + "</style>";
      this.safeString = this.sanitizer.bypassSecurityTrustHtml(string);
    }
  }
}

然后像这样使用它:

mySample.component.html:

<app-local-css [style]="'body{background:green !important;}'"></app-local-css>
// OR
<app-local-css [scriptURL]="'/path/to/file.css'"></app-local-css>

Angular 正在做客户端渲染,这是个坏消息,因为你没有单独的页面。 不过,您有几种可能的解决方案:

1. 单独的页面

您可以使用或不使用 Angular 创建另一个页面,其中包含您需要的 CSS 并加载该页面。 在实现此目的的最简单方法中,另一个页面将具有不同的 URL。 如果您不喜欢使用不同的 URL,那么您可以隐藏页面的内容并在iframe显示另一个页面。 诚然,这将是一个笨拙的解决方案,但它是一个解决方案。

2. 客户端CSS渲染

除了加载 CSS,您还可以拥有一个控制全局 CSS 规则的组件,并与您的视图名称匹配。 您会将模板值呈现给属性,例如:

@media print{
    @page{
        margin:0;
    }
    body{
        margin:30px;
    }
}

当您访问需要激活它的页面时,您只需使用基于模板生成并添加到headstyle HTML 元素初始化一个属性。 一旦您离开给定的视图,您的组件将检测到该事件并remove()该元素。 如果你选择这个解决方案,那么明智的做法是确保你在更一般的条款上支持它,这样如果一些新的视图将有他们自定义的全局 CSS,那么它们将来会很容易集成到你的项目中.

3. 身体类

每当要更改样式时,您都可以在body添加/删除一些custom-print或任何类。 通过这种方式,您可以将 CSS 仅添加一次到您的 HTML 并相应地更改规则,例如:

body.custom-print {
    margin: 30px;
}

这将是一个巧妙的解决方案,但在您的情况下,问题是您也有一个@page规则,我不确定您如何使其依赖于正文类或其他一些 HTML 属性。 如果我是你,我会为此做很多实验。

4. iframe 暂存

您可以避免在您的主页中使用该 CSS,但是会有一个隐藏的iframe ,您可以在其中拥有 CSS,并且只需将内容复制到 CSS 中,一旦加载,就打印出来。

不要从苹果改变整个身体。 相反,需要进行一些更改。

  1. 在 app 组件中,为你是否在 Apple 上持有一个布尔值,并为 scss 中定义的类使用 ngClass。

  2. 在 appComponent 中跟踪您所在的路线,并相应地设置 isApple

  3. 在所有 html 周围添加一个 div,以便容器采用全尺寸

  4. 添加全局 html,body 设置高度为 100% 让你到处都能看到颜色

  5. 删除苹果中的身体覆盖

所以,appComponent.ts:

  isApple: Boolean;
  constructor(router: Router) {
    router.events.subscribe(v => {
      if (v instanceof NavigationEnd) {
        this.isApple = v.url === "/apple";
      }
    });
  }

appComponent.html:

<div [ngClass]="{'red':isApple}" class="container">
    <p>
        There are two components: Apple and Banana. Switching between them will show
        the problem.
    </p>

    <router-outlet></router-outlet>
</div>

应用组件.scss


.red {
  background-color: red;
}

.container {
  height: 100%;
}

apple.component.scss(移除主体)

/*Sample "global" CSS, that affects something outside the current component.*/
::ng-deep {
  @media print {
    @page {
      margin: 0;
    }
  }
}

style.scss(全局)

html, body {
  height: 100%;
}

您可以在此 Stackblitz 链接中完全看到这一点

您可以在组件中添加不同的 css 文件(例如 app-task.component.ts):

@Component({
  selector: 'app-task',
  templateUrl: './app-task.component.html',
  styleUrls: ['./app-task.component.scss', './styles2.scss', './styles3.scss']
})

在此示例中,样式文件与组件位于同一文件夹中,但这不是最佳选择:例如,您必须将文件放在资产中。 另外,请注意样式的线程,因为您放置的第一个将放在第二个之前(显然)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM