浅谈Angular中组件样式的工作原理

在开发 Angular 组件的过程中,我们习惯把组件的样式写在对应的 css 文件中,但是一直不了解 Angular 是怎样做到样式隔离的,比如在 A 组件中写了 h1 { color: red },这个样式只会在 A 组件中生效,而不会影响到其他的组件。为了探究原理,就有了这篇文章,以下内容基于 Angular CLI 10.1.1 版本创建。

组件样式工作原理

探索

首先用 Angular CLI 创建一个新的 Angular 项目,删除 app.component.html 中的所有内容,替换成如下内容

<h1>App Component</h1>
<button class=red-button>Button</button>

app.component.css添加如下内容

.red-button {
  color: red;
}

运行时有如下 html 代码

<app-root _nghost-ydo-c11= ng-version=10.1.1>
  <h2 _ngcontent-ydo-c11=>App component</h2>
  <button _ngcontent-ydo-c11= class=red-button>Button</button>
</app-root>

可以看到在在 app-root 元素上有一个名为 _nghost-ydo-c11属性(property),app-root 里面的两个元素都有一个名为 _ngcontent-ydo-c11属性。【相关教程推荐:《angular教程》】

那么这些属性是用来做什么的呢?

为了更好的理解,我们先创建一个独立的组件,新建文件 blue-button.component.ts内容如下:

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

@Component({
  selector: 'app-blue-button',
  template: `
    <h2>Blue button component</h2>
    <button class=blue-button>Button</button>
  `,
  styles: [`
    .blue-button {
      background: blue;
    }
  `]
})
export class BlueButtonComponent {}

放到 app.component.html 中运行后,会看到如下 html 代码

1.png

可以看到 app-blue-button 中也有一个_nghost-xxx 开头的属性,还有一个app-root 中其他元素相同的属性。而在组件里面的两个元素都有名为 _ngcontent-yke-c11属性

由于每次运行,Angular 生成属性字符串都是随机的,所以后面的代码如果出现了类似的属性都是按照这个截图对应的。

总结

通过观察我们可以总结出:

  • 每个组件的宿主元素都会被分配一个唯一的属性,具体取决于组件的处理顺序,在例子中就是 _nghost_xxx
  • 每个组件模板中的每个元素还会被分配一个该组件特有的属性,在例子中就是 _ngcontent_xxx

那么这些属性是怎样用于样式隔离的呢?

这些属性可以和 CSS 结合起来,比如当我们查看例子中蓝色按钮的样式时,会看到这样的 css:

.blue-button[_ngcontent-yke-c11] {
    background: blue;
}

可以看出,Angular 通过这种方式使 blue-button 类只能应用于有这个属性的元素上,而不会影响到其他组件中的元素。

知道了 Angular 对样式隔离的行为,那么 Angular 又是如何做到这些的呢?

在应用启动时,Angular 将通过 styles 或 styleUrls 组件属性来查看哪些样式与哪些组件相关联。之后Angular 会将这些样式和该组件中元素特有的属性应用到一起,将生成的 css 代码包裹在一个 style 标签中并放到 header 里。

2.png

相关文章

前言 做过web项目开发的人对layer弹层组件肯定不陌生,作为l...
前言 前端表单校验是过滤无效数据、假数据、有毒数据的第一步...
前言 图片上传是web项目常见的需求,我基于之前的博客的代码...
前言 导出Excel文件这个功能,通常都是在后端实现返回前端一...
前言 众所周知,js是单线程的,从上往下,从左往右依次执行,...
前言 项目开发中,我们可能会碰到这样的需求:select标签,禁...