Angular 碎片 —— 样式封装

目录

综述

不封装

仿真(Emulated)封装

原生(Native)封装

参考资料

综述

本文介绍Angular中的样式封装机制,以及背后的基本原理,供您参考。

我们在写一个Angular Component的时候经常要指定该Component需要的样式。样式可以通过inline的方式在styles属性中定义,也可以通过指定一个外部样式文件定义需要的CSS。无论哪种方式,定义的样式都只在当前Component可见,其他Component无法访问。这是Angular Component对样式处理的默认行为,但不是唯一行为。事实上,组件的encapsulation属性可以配置上述行为。下面我来一一介绍。

不封装

这种情况下,encapsulation的属性值为None,即不对样式进行封装。此时,Component中定义的样式会暴露给其他组件。代码如下:

@Component({
  selector: 'craft-man-styles',
  templateUrl: './craft-man-styles.component.html',
  styleUrls: ['./craft-man-styles.component.css'],
  encapsulation: ViewEncapsulation.None
})

从Chrome的调试器中,我们可以看到生成的HTML以及样式如下:

我们可以看到,在head标签中定义了新的style标签,用来存放我们自定义的样式craft-man-title。这个style标签没有任何修饰,因此是全局可见的。这意味着,如果这个样式的名称被定义过,那么就会产生冲突。

仿真(Emulated)封装

下面我们再来看看Emulated 的样式封装。这是Angular Component默认采用的封装方式。所谓“仿真”,是相对于第三种方式“原生”而言的。意思是它虽然实现了样式的封装,但是一种类似work around的方式。定义Component时只需要设置:

encapsulation: ViewEncapsulation.Emulated

相应的在生成的HTML与None的方式有所不同:

请注意在style标签中生成的CSS样式,在名称后面附带了属性选择器[_ngcontent-c0]。相应地在Component的template中也使用了同样的属性。因此,这个style中的CSS样式只会应用于我们自己的Component。这个属性选择器是Angular在运行时生成的,目的就是将自定义的CSS作用域限定在组件内部。这些样式外部是可见的,但是只会在应用了特定属性的元素上应用,因此是一种仿真封装

原生(Native)封装

最后我们来看看原生封装方式。在代码中设置如下:

encapsulation: ViewEncapsulation.Native

与仿真封装不同的是,该方式会使用影子DOM(Shadow DOM)的技术来实现样式封装。这里简单介绍下Shadow DOM的概念。

Shadow DOM是Web Component标准中的一个重要概念。它提供了一种DOM的嵌套和封装方式。通常来说,一个页面的document只对应一个DOM Tree,而Shadow DOM可以帮助我们将一个不可见的影子DOM嵌入页面上的某个元素,并且这个影子DOM只在该元素内部可见。Shadow DOM提供了一定的封装性,比如样式、JavaScript代码都可以封装到DOM内部。这就是所谓“原生”封装的内涵了。如果想要在某个元素上定义一个Shadow DOM,可以使用createShadowRoot()函数。想更深入了解Shadow DOM的相关技术,可以参考下面资料中的链接。

我们可以看看这种情况下的页面:

我们看到自定义的样式没有在head标签中生成,而是直接写在Component的template中。注意#shadow-root (open)这个特殊元素,它就是浏览器生成的Shadow DOM。我们自定义的Component中所有属性包括HTML、CSS等都定义在这个嵌套DOM中,该DOM对其他元素并不可见,从而实现了样式封装。

参考资料

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值