1

如何在 Angular 中为一页添加单独的 CSS?

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

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

::ng-deep但是在这里用or将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;
    }
  }

为什么它不起作用:

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

4

4 回答 4

2

解决了!

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

这是一个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>
于 2020-11-17T11:54:41.310 回答
1

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

1.单独的页面

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

2.客户端CSS渲染

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

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

当您访问需要激活此功能的页面时,您只需使用style基于模板生成并添加到head. 一旦您离开给定的视图,您的组件就会检测到该事件并检测remove()该元素。如果您选择此解决方案,那么明智的做法是确保您以更一般的方式支持此解决方案,这样如果一些新视图将具有其自定义的全局 CSS,那么将来它们将很容易集成到您的项目中.

3.体类

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

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

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

4. iframe 分期

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

于 2020-11-17T11:53:12.480 回答
0

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

  1. 在应用程序组件中,保存一个布尔值来判断你是否在苹果上,并将 ngClass 用于 scss 中定义的类。

  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";
      }
    });
  }

应用组件.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;
    }
  }
}

样式.scss(全局)

html, body {
  height: 100%;
}

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

于 2020-11-17T11:21:36.547 回答
-1

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

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

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

于 2020-11-11T10:20:45.547 回答