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

Pho*_*404 1 css components encapsulation angular-material angular

我创建了一个<nextgen-table></nextgen-table>基于Mat-table(角度材质)的共享组件()。在项目中使用此组件时,发现我需要更改表列的行为(宽度)。

我已nextgen-table在其他组件中导出(假设 X, Y ),其中nextgen-table当然是子组件。

要更改 mat-table 特定列的宽度,我必须使用如下内容:

mat-cell:nth-child(1),
mat-header-cell:nth-child(1) {
    flex: 0 0 40%;
    text-align: left;
} 
mat-cell:nth-child(2),
mat-header-cell:nth-child(2) {
    flex: 0 0 20%;
}
Run Code Online (Sandbox Code Playgroud)

上面的 CSS 代码是我在 X.component.css 中实现的,但我猜它是因为封装而无法工作。

经过一番搜索后,我找到了只需在 的 Component 装饰器中添加 即可正常工作的解决方案。在这个解决方案之后,我从组件 X 导航到组件 Y,其中我没有实现上述 CSS 代码。但是组件 Y 具有前两列,因为我只想要组件 X,但不知何故组件 Y 也具有我不想要的组件 Y。encapsulation: ViewEncapsulation.Nonex.component.ts

所以我的问题是如何nextgen-table从父组件更新仅适用于父组件而不适用于其他组件的样式。

我也尝试过使用

:host(mat-cell:nth-child(1)){
  flex: 0 0 40%;
  text-align: left;
}

:host(mat-header-cell:nth-child(1)) {
    flex: 0 0 40%;
    text-align: left;
}
Run Code Online (Sandbox Code Playgroud)

但什么都没有发生/改变。

先谢谢您的帮助

Dav*_*vid 5

您可以使用::ng-deep 伪类来专门针对子元素,而无需更改整个组件的视图封装(这意味着其所有规则都会泄漏)。

注意::ng-deep自几个主要版本以来已被标记为已弃用,但在找到解决方法之前他们不会删除支持。

父X.html

<div class="compContainer">
    <nextgen-table></nextgen-table>
</div>
Run Code Online (Sandbox Code Playgroud)

父X.scss

::ng-deep .compContainer nextgen-table
{
    mat-cell:nth-child(1),
    mat-header-cell:nth-child(1) {
        flex: 0 0 40%;
        text-align: left;
    } 
    mat-cell:nth-child(2),
    mat-header-cell:nth-child(2) {
        flex: 0 0 20%;
    }
}
Run Code Online (Sandbox Code Playgroud)

您还可以将 css 规则添加到全局style.scss文件中。

//Rules for parent X
app-parent-componentX .compContainer nextgen-table
{
    mat-cell...
}

//Rules for a parent Y
app-parent-componentY .compContainer nextgen-table
{
    mat-cell...
}
Run Code Online (Sandbox Code Playgroud)


Hir*_*ekh 5

您需要做的就是在 X 或 Y 组件中使用伪类选择器:host::ng-deep

这是工作演示

这是快速解释。

为内部编写的样式<nextgen-table>可以说nextgen-table.component.css是通过为每种样式添加特定属性来由 Angular 封装的。即如果你写过类似的东西,

.mat-header-cell{
    background-color: #ff0000;
}
Run Code Online (Sandbox Code Playgroud)

然后它就变成了类似的东西

.mat-header-cell[_ngcontent-c29]
    background-color: #ff0000;
}
Run Code Online (Sandbox Code Playgroud)

所以我们需要做的就是在组件 X 或组件 Y 中重写这个样式。

我们有::ng-deep伪选择器,它将阻止 Angular 封装组件的 CSS。

但是使用::ng-deep也会将我们的 CSS 泄漏到父组件上。因此,为了防止这种情况,我们需要封装::ng-deep样式。为此,我们可以使用:host伪选择器。

所以如果我们在组件 X 中编写以下 css,

:host ::ng-deep .x-table .mat-header-cell{
  background-color: lightblue;
}
Run Code Online (Sandbox Code Playgroud)

然后它会变成类似的东西

[_nghost-c82] .x-table .mat-header-cell {
    background-color: lightblue;
}
Run Code Online (Sandbox Code Playgroud)

现在,上面的 CSS 选择比表格组件中编写的样式具有更高的优先级.mat-header-cell[_ngcontent-c29]

这就是我们如何在任何父组件中覆盖子组件的样式。我希望这个能帮上忙。

更新:正如你在Angular 的官方文档 中看到的那样,它 ::ng-deep已被弃用。

阴影穿透后代组合器已被弃用,并且主要浏览器和工具正在删除支持。因此,我们计划放弃对 Angular 的支持(对于 /deep/、>>> 和 ::ng-deep 的所有 3 个)。在那之前,应该首选 ::ng-deep,以获得与工具更广泛的兼容性。

所以如果你不想依赖的::ng-deep

您可以ViewEncapsulation.None<nextgen-table>您已经尝试过的表格组件中使用。演示在这里

为了防止样式渗透到其他组件中,您可以通过在所有样式前面添加选择器来限制表格样式的范围,如下所示。

nextgen-table .mat-header-cell{
    background-color: #ff0000;
}
Run Code Online (Sandbox Code Playgroud)

然后对 X 组件执行相同的操作。

  • 使用禁用视图封装ViewEncapsulation.None
  • 然后通过编写比表的实际样式具有更高特异性的样式来覆盖表组件上的样式。

禁用 X 组件中的封装,

@Component({
  selector: "app-x",
  styleUrls: ["x.component.css"],
  templateUrl: "x.component.html",
  encapsulation: ViewEncapsulation.None
})
export class XComponent {

}
Run Code Online (Sandbox Code Playgroud)

然后覆盖表的组件样式x.compoent.css

app-x nextgen-table .mat-header-cell{
  background-color: lightblue;
}
Run Code Online (Sandbox Code Playgroud)

如果您不想禁用视图封装,那么您可以直接将样式写入全局样式表 styles.css

请记住,这都是关于覆盖您的样式并确定其范围。