在介绍 ViewEncapsulation
之前,我们先来介绍一下 Web Components 标准。
Web Components
近年来,Web 开发者们通过插件或者模块的形式在网上分享自己的代码,便于其他开发者们复用这些优秀的代码。同样的故事不断发生,人们不断的复用 JavaScript 文件,然后是 CSS 文件,当然还有 HTML 片段。但是你又必须祈祷这些引入的代码不会影响到你的网站或者 Web App。
Web Components 是解决这类问题最好的良药,它通过一种标准化的非侵入的方式封装一个组件,每个组件能组织好它自身的 HTML 结构、CSS 样式、JavaScript 代码,并且不会干扰页面上的其他元素。
Web Components 由以下四种技术组成:
- Custom Elements - 自定义元素
- HTML Templates - HTML模板
- Shadow DOM - 影子DOM
- HTML Imports - HTML导入
因为 Shadow DOM 与 Angular ViewEncapsulation 相关, 所以这篇文章我们主要介绍 Shadow DOM 相关的内容。
Shadow DOM
--------- ----- ----- ---------- ------ ----- ---------------- ------------- ----------- ------ ---------------- --------------- - ------ ----- - -------- -------------- ------ -- -------------------------- ------ --------- ---- ------------------------- ------------ -------- -- ----------- ----- --- ---------- - -------------------------------------- -- ------------ ----- --- ---------- - ------------------------------ -- --------------------------------- -------------------- - --- ------------------------- ------ ----------- --------- ------- ------
以上代码成功运行后,如下图:
我们发现在 #shadow-root
中的元素,不受我们外界定义的 CSS shadowroot_son
类影响。因此我们可以利用 Shadow DOM 来封装我们自定义的 HTML 标签、CSS 样式和 JavaScript 代码。需要注意的是 Shadow DOM 兼容性还不是很好,具体请参考 - Can I Use Shadow DOM 。
接下来我们开始介绍 Angular ViewEncapsulation Modes:
ViewEncapsulation
ViewEncapsulation 允许设置三个可选的值:
- ViewEncapsulation.Emulated - 无 Shadow DOM,但是通过 Angular 提供的样式包装机制来封装组件,使得组件的样式不受外部影响。这是 Angular 的默认设置。
- ViewEncapsulation.Native - 使用原生的 Shadow DOM 特性
- ViewEncapsulation.None - 无 Shadow DOM,并且也无样式包装
ViewEncapsulation 枚举定义:
------ ---- ----------------- - --------- -- --- ------- ---- -
ViewEncapsulation.None
------ - ---------- ----------------- - ---- ---------------- ------------ --------- --------- --------- - ----------- -- ------- ---------- -- ------------------- ------------ -- ------- -- ------ - ----------- ----- ------ ------ - --- -------------- ---------------------- -- ---- - -------- - ------ -- ------ ----- ------------ - ----- ------ - ------------ -
运行后的结果:
ViewEncapsulation.None 设置的结果是没有 Shadow DOM,并且所有的样式都应用到整个 document,换句话说,组件的样式会受外界影响,可能被覆盖掉。
ViewEncapsulation.Emulated
------ - ---------- ----------------- - ---- ---------------- ------------ --------- --------- ---- -------------- -------------------------- -- ---- - -------- - ------ -- ------ ----- ------------ - ----- ------ - ------------ -
运行后的结果:
ViewEncapsulation.Emulated 设置的结果是没有 Shadow DOM,但是通过 Angular 提供的样式包装机制来封装组件,使得组件的样式不受外部影响。虽然样式仍然是应用到整个 document,但 Angular 为 .greet
类创建了一个 [_ngcontent-cmy-0]
选择器。可以看出,我们为组件定义的样式,被 Angular 修改了。其中的 _nghost-cmy-*
和 _ngcontent-cmy-*
用来实现局部的样式。
ViewEncapsulation.Native
------ - ---------- ----------------- - ---- ---------------- ------------ --------- --------- ---- -------------- ------------------------ -- ---- - -------- - ------ -- ------ ----- ------------ - ----- ------ - ------------ -
运行后的结果:
ViewEncapsulation.Native 设置的结果是使用原生的 Shadow DOM 特性。Angular 会把组件按照浏览器支持的 Shadow DOM 形式渲染,渲染结果如上图所示。