从父应用样式

Posted

技术标签:

【中文标题】从父应用样式【英文标题】:Apply styles from parent 【发布时间】:2016-05-06 18:53:10 【问题描述】:

假设我有一个带有这个模板的组件:

<div class="frame">
  <span class="user-defined-text">text</span>
</div>
<style>
  span  font-size: 3em; 
  .frame  ... 
</style>

如何合并应用于组件的样式,例如

<custom-component [text]="'Some text'">
<style>custom-component  font-weight: bold; </style>

所以最终输出“Some text”是粗体 3em 大小?

有没有更好的方法来获取宿主元素的计算样式,例如,我可以将宿主的 background-color 应用到模板中某个元素的 border-color

【问题讨论】:

您不认为将样式表放在全局级别以便您可以使用styleUrl 属性不是很好吗。还是只想通过这种方式实现? 这个想法是,在不同的地方,组件可以以不同的样式重复使用。例如。在某些地方是粗体的按钮,或者在某些地方是较大的文本。 Angular2 似乎停止了组件的所有样式,因此它们不会进一步传播。 一个 :children 选择器或类似的允许组件访问其子级的功能将是一个非常简洁的功能。模拟视图封装也应该是可能的,但我不确定他们是否想做与原生 shadow dom 有很大不同的事情,因为使用原生是未来的目标。 【参考方案1】: 设置encapsulation: ViewEncapsulation.None 以允许应用来自外部的样式。
import Component, ViewEncapsulation from '@angular/core';

@Component(
  selector: 'custom-component',
  encapsulation: ViewEncapsulation.None
)
export class Custom 
使用styleUrl 结合主机选择器添加 CSS 文件
:host(.someClass) 
      background-color: blue;


<custom-component class="someClass"></custom-component>

根据添加到元素的类来应用样式。

【讨论】:

假设我使用第一个策略:我可以通过为类名使用前缀来避免名称冲突。但是,除非我也禁用父组件的封装,否则它的所有样式仍然仅限于其元素,并且不会进一步传播。 (即,在使用模拟封装时,它们都具有 [ng...] 限定符) EmulatedNative 用于样式封装。您必须在任何地方禁用它才能应用全局样式。无论如何,我建议使用第二种策略。这样您就可以同时拥有封装和全局样式。您可以为每个组件添加多个styleUrls。在适当的地方添加一个全局变量和一个局部变量。如果您首先添加本地,您应该能够通过全局样式覆盖本地样式以自定义“默认”样式(如果可行,我自己还没有尝试过,如果不可行,我会认为它是一个错误)。 对于第二种策略,子组件不是需要知道所有可能的父组件才能自定义特定实例吗? 不确定你的意思。直接父级应该向组件添加一个类(其中&lt;custom-component&gt; 被添加到它的模板中。&lt;custom-component&gt; 然后应用匹配.someClass 的样式。:host 表示“自我”,:host(.someClass) 表示“自我与类someClass" 我的意思是,如果我希望自定义组件具有color: red,那么父级需要应用class="color-red" 之类的东西,而子级需要:host(.color-red) span color: red; 。这意味着我需要知道所有这些可能的课程......还是我错过了什么?【参考方案2】:

我知道这是旧的,但我觉得这应该更明显。您可以使用/deep/ 选择器强制样式通过子组件树向下进入所有子组件视图。 /deep/ 选择器适用于任何深度的嵌套组件,它适用于组件的视图子项和内容子项。

我觉得这更干净,更容易实现。

parent.css

/deep/ .class 
    background-color: red;

https://angular.io/docs/ts/latest/guide/component-styles.html

【讨论】:

不适用于指令 /deep/ 在聚合物和 Chrome 中已被弃用(可能很快会在 Angular 中使用)。并且只能与模拟视图封装一起使用。 在 Angular 4.3 之前,使用 /deep/ 或 >>> 代替 ::ng-deep。这两种表示法都已被浏览器弃用,因此 ::ng-deep 现在是临时解决方法。 alligator.io/angular/styles-between-components-angular【参考方案3】:

关于 CSS,组件支持 shadow DOM。这意味着他们的风格是孤立的。默认模式是隔离的。所以你需要在组件中定义 CSS 样式(styles 属性)。

您也可以将封装模式更改为ViewEncapsulation.None。这样你的组件就可以看到父组件的样式:

@Component(
  selector: 'child',
  encapsulation: ViewEncapsulation.None,
  (...)
)
export class MyComponent 
  (...)

希望对你有帮助 蒂埃里

【讨论】:

【参考方案4】:

使用 :host 伪类选择器来设置任何 &lt;custom-component&gt; 的样式。

我们不能通过使用类将 css 样式写入自定义元素。

例子

<custom-component class="custom-comp" [text]="'Some text'">

.custom-comp 
  font-weight: bold;
  color: green;

为此,我们可以使用 :host 选择器来设置如下样式

@Component(
  selector: 'custom-component',
  templateUrl: './custom-component.html',
  styleUrls: ['./custom-component.scss']
)

在 custom-component.scss 中

:host 
  font-weight: bold;
  color: green;

您可以在 Angular4 的官方文档中阅读更多关于样式 :host 元素的信息

【讨论】:

以上是关于从父应用样式的主要内容,如果未能解决你的问题,请参考以下文章

如何仅将 css 样式应用于特定的 Vue 组件及其子组件?

CSS简介

如何从父级修改组件的样式?

样式化组件——从父级访问道具

javascript中子窗口如何从父窗口继承css样式?

从父组件角度更改子组件样式但不是全局更改