引导

这是一个很简单的话题,但是你很难在搜索到一篇比较完整的介绍它的文章,或者说单纯的告诉你 ViewEncapsulation 的用法而已,这在实际项目中远远不够的。

一、封装模式

分别为:

  • Native 原先浏览器Shadow DOM行为。

  • Emulated 仿真模式,通过Angular来模拟类似Shadow DOM的行为。

  • None 无任何封装行为。

以上三种模式唯一的区别在于Shadow DOM,当然其作用是让组件的样式只进不出,换言之即组件内的样式不会影响到外部组件。有关于Shadow DOM更多的细节不在这里讨论。

三者的表现形式

假定使用以下代码:

@Component({template: `<h1>test</h1>`,styles: [`h1 { color: #f50; }`],encapsulation: ViewEncapsulation.Native
})

在不同模式下产生的HTML&CSS风格都不尽相同,了解这些不一样尤为重要。它们分别为:

Native:

#shadow-root (open)<style>h1 { color: #f50; }</style><h1>test</h1>

Emulated:

<style>h1[_ngcontent-c0] { color: #f50; }</style>
<h1 _ngcontent-c0>test</h1>

None:

<style>h1 { color: #f50; }</style>
<h1>test</h1>

Native & None 在内容是一样的,但其后者会影响至其他外部组件的 h1 元素。

二、组件样式

组件样式的封装模式取决于我们对 encapsulation 的配置,例如上面的示例。当然你可以了在 main.ts 时为所有组件统一设定一种行的模式,例如:

platformBrowserDynamic().bootstrapModule(AppModule, {defaultEncapsulation: ViewEncapsulation.None
})

虽然三种模式都有不同的风格,但对于一个组件而言,如果没有一很合理的使用风格在实际项目中会让我们很头疼,特别是当项目中使用第三方组件库(例如:ngx-bootstrap、ng-zorro-antd、material2 等)时,有时很容易受组件库的影响抑或需要让组件库与业务组件样式做一些微调时,了解一些细节非常重要。

例如一个用于渲染页面标头名曰:app-header 组件,其中 <nz-breadcrumb> 面包屑 默认情况下它会对最后一项进行加粗,但假设这不是我们希望的,而应该是一个不加粗和其他项一样的文本:

<nz-breadcrumb><nz-breadcrumb-item>Home</nz-breadcrumb-item><nz-breadcrumb-item>Detail</nz-breadcrumb-item>
</nz-breadcrumb>

最终生成的HTML是这样子:

<nz-breadcrumb _ngcontent-c1="" class="ant-breadcrumb"><nz-breadcrumb-item _ngcontent-c1=""><span class="ant-breadcrumb-link">Home</span><span class="ant-breadcrumb-separator">/</span></nz-breadcrumb-item><nz-breadcrumb-item _ngcontent-c1=""><span class="ant-breadcrumb-link">Detail</span><span class="ant-breadcrumb-separator">/</span></nz-breadcrumb-item></nz-breadcrumb>

倘若你不假思索的在 app-header 组件的 styles 属性中加上:

.ant-breadcrumb-link {font-weight: normal;
}

正如你期望的那样,可能不一定会有你想要的结果,亦或的结果可能会存在隐患。前面我说过三种模式唯一的区别在于Shadow DOM,因此说白了是两种不同的结果。

若组件设定为 None 模式,而会生效,但只要 app-header 组件出现过一次在未来所有即使不再使用 app-header 组件的情况下所有的面包屑的最后一项都是是不加粗的,这便是我说的隐患。

反之,对于 Shadow 行为,它会为 nz-breadcrumb 创建一个额外的属性 _ngcontent-c1标识(不管是 NativeEmulated 本质是一样的)所设定的样式仅限于 app-header 组件当中。而 Angular 中即采用 :host 来表示组件自身,所以前面的CSS样式应该变成这样:

:host .ant-breadcrumb-link {font-weight: normal;
}

最后生成的样式会变成这样:

[_nghost-c1] .ant-breadcrumb-link[_ngcontent-c1] {font-weight: normal;
}

我认为我们没有必要去理解生成的标识符是怎么样,只需要知道 :host 表示组件自身。

然而我们会发现,对于第三方组件 nz-breadcrumb 组件而言,.ant-breadcrumb-link 是其组件内部某个HTML元素的 class 而已,且它有自己的一套组件封装规则。但我们生成的CSS中包括了一个奇怪的字符 [_ngcontent-c1],最终导致 app-header 组件样式无法改变第三方组件 nz-breadcrumb 组件内容的样式。

这是很合理的,我的领地不可侵犯,Angular 组件本身即是 Web Component 标准的具体实现。

难道我们没有办法侵犯第三方组件了吗?好在 Angular 提供了一种对未来工具更好兼容性的命令 ::ng-deep 来强制样式允许侵入子组件。

:host ::ng-deep .ant-breadcrumb-link {font-weight: normal;
}

生成的CSS会是这样:

[_nghost-c1] .ant-breadcrumb-link {font-weight: normal;
}

最终这个不加粗的效果只会在 app-header 组件内部有效。

总结

熟悉 :host::ng-deep 组合用法对组件样式的构建很关键,Angular 组件有自己的业务逻辑、样式、HTML模板它们是构建一个 Web Component 的基础技术核心。

希望此篇能帮助大家更好理解组件样式。

Happy coding!

关于Angular样式封装相关推荐

  1. 自定义Scrollbar样式-封装复用

    自定义Scrollbar样式 文章目录 自定义Scrollbar样式 进入正文 入口函数 参数处理 样式添加 逻辑整合 私有成员 结尾 旧题新解,自定义scrollbar样式,是一个前端程序员经常遇到 ...

  2. 使用amaze ui的分页样式封装一个通用的JS分页控件

    作为一名码农,天天百度.偶尔谷歌,所有代码全靠copy,用第三方插件,偶尔也想着造造轮子,毕竟自己的骨肉总归比较亲. 今天有点空闲时间,想起我们公司之前套的页面的分页插件上还有bug,而写那个分页插件 ...

  3. angular中封装fancyBox(图片预览)

    首先在官网下载最新版的fancyBox(一定要去最新网站,以前依赖的jquery版本偏低),附上链接:http://fancyapps.com/fancybox/3/ 然后在项目中引用jquery,然 ...

  4. 一步一步学Silverlight 2系列(8):使用样式封装控件观感

    概述 Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, ...

  5. CSS常用 Less 公共样式封装

    /------------------------------------- ├ 布局 ┆ └------------------------------------/// 盒子宽高 .size(@w ...

  6. angular使用什么样的样式_Angular 样式使用注意事项

    预处理器 如果是用angular-cli生成的项目,可以在angular.json中配置你喜欢的样式预处理器 "schematics": { "@schematics/a ...

  7. JS一起学05:Date对象、封闭空间、函数传参和封装、获取非行间样式、字符串操作

    一.Date对象 1. 获取 oDate.getFullYear() 获取年份 oDate.getMonth()+1  获取月份 0-11----->1-12 oDate.getDate() 获 ...

  8. Angular项目目录结构

    前言:不支持MakeDown的博客园调格式的话,真的写到快o(╥﹏╥)o了,所以老夫还是转战到CSDN吧,这边就不更新啦啦啦~ CSDN地址:https://blog.csdn.net/Night20 ...

  9. 获取Angular中的AngularJS功能

    介绍 ( Introduction ) If you have solid experience with AngularJS 1.x, you're well aware of the framew ...

最新文章

  1. 2014-06-27nbsp;20:47
  2. 使用numpy遇到ValueError: The truth value of an array with more than one element is ambiguous
  3. Java在生活中的应用盘点!
  4. 使用SELECT 和OPEN CURSOR 读取big table的性能比较
  5. 软件之间的数据格式对接往往将_XRD数据格式的转换和TXT格式数据正确导入Jade的办法...
  6. 60佳优秀的 Photoshop 网页制作教程【下篇】
  7. rmi远程代码执行漏洞_fastjson远程代码执行漏洞复现
  8. linux java 环境配置_linux下java开发环境配置
  9. php怎么写确认密码,如何在Laravel 5中验证当前密码,新密码和新密码的确认? - php...
  10. 唐尼vr眼镜好吗_裸眼3DVR和全息投影有什么区别 他们之间谁更好一些
  11. Dapper and Repository Pattern in MVC
  12. 个人收藏的一些资料(一)Installshield制作友好的更新
  13. 【渝粤教育】国家开放大学2019年春季 233学前儿童语言教育 参考试题
  14. R语言模型中的加总偏误与内生性:一种数值模拟方法
  15. How to deploy Odoo 11 on Ubuntu 18.04
  16. 怎么取消wps云服务器_关闭手机版wps云服务器
  17. mysql触发器更新自己表_mysql触发器实例:更新表数据之前触发
  18. 零中频接收机频率转换图_德国Ramp;S罗德与施瓦茨EMI测试接收机ESR系列
  19. React基础(肆)———状态和循环渲染
  20. linux mint 卸载桌面,Linux Mint 默认桌面 Cinnamon 1.6 正式发布

热门文章

  1. jquery获取和设置属性_jQuery获取属性,设置属性,删除属性
  2. scala面试问题_Scala高级面试问答
  3. C++和C语言的前世今生,两者有什么血缘关系?
  4. DotNetTextBox V3.0 所见即所得编辑器控件Ver3.2.5 Free(免费版)
  5. 已开源|码上用它开始Flutter混合开发——FlutterBoost
  6. 【实战】Vue 中 Props 值因异步获取导致的报错问题解析
  7. 【工具使用系列】关于 MATLAB 神经网络故障诊断,你需要知道的事
  8. iOS 开发,该如何解决弹窗的设计问题?
  9. MyBatis Generator(MBG)设计哲学与致歉
  10. myeclipse 快捷键(转载)