angular :host_如何覆盖开源组件库样式?Angular样式封装浅析

如果你使用过第三方插件,一定经历过覆盖插件原有样式

此处要感谢阿里开源组件库ng-zorro,简洁实用等特性,完美契合了B端产品的需求。

NG-ZORRO/ng-zorro-antd​github.com
58c352c234323f2e6a2c9a47fcc9e705.png

使用过程中碰到了一个尴尬的问题,需要覆盖组件原有样式。覆盖方式可分为两种

  1. 更改组件封装模式为ViewEncapsulation.None
  2. 使用 :host ::ng-deep 选择器

下面以这两种方式为出发点,分析下Angular样式封装的原理

Angular视图的封装模式

在Angular中,视图封装分为三种,Native / Emulated / None,其中Emulated为组件默认封装模式,具体介绍戳官网传送门

https://angular.cn/guide/component-styles#view-encapsulation​angular.cn

众所周知,css中没有作用域的概念,那么Angular是如何实现组件样式封装的呢?

我们先来看一个简单的例子,p标签的样式定义分别为:全局样式红色,app component黄色,demo list蓝色。在默认封装模式下,编译后的代码如下

bf3816f6b5f5bdc4fd5ddf8f616a404b.png
编译后的模版代码

93a98673ca81fce2929de34ea40e7ea7.png
编辑后的样式代码

从图中可以看到,模版代码中自定义标签上增加了一些特殊属性,如"_nghost-c0"、"_ngcontent-c0",而编译后的css代码则加上了对应的选择器。通过这种方式,组件内定义的样式,仅仅作用于组件内部,而不会影响到子组件或页面内其他组件。

在默认封装模式Emulated下,定义的样式,可以理解为局部变量,只作用于当前组件,这个组件之外的地方,无法访问。也就是官方文档中描述的,组件样式出不去。这种情况下,全局的样式依然可以进得来,对应上图中p标签红色的定义,来自全局样式,依然可以作用在组件中。

Native与默认的Emulated表现形式区别只有一点,全局样式能否影响到组件。Native模式的组件,它的样式是不受全局样式影响的,这得益于shadow DOM。如果开发过程中,某一个组件,不想受到项目中全局样式的影响,可以采用Native的方式。

None不再多做讲解,它会让样式回归自然状态,所有的样式都如同写在全局作用域中,全局样式进得来,组件内的样式也出的去。个人认为,如果不是有特殊的原因,最好不要使用这种方式。

在了解三种视图封装模式后,我们果断放弃了第一种覆盖方法。

三种特殊的选择器

Angular 从 Shadow DOM中借鉴了三种特殊的选择器,分别是:host :host-context::ng-deep

:host 用于选中宿主元素(这也是唯一一种选中宿主元素的方式),添加了这个选择器之后,编译出的css会增加宿主元素的选择器,也就是图中的 _nghost-c1

2d0d3f8386a1e00cd3043e8b97c4e3c0.png
demo list 样式增加:host选择器后的效果

:host-context 就比较厉害了,它可以指定当前样式生效的条件,逐级查找当前组件的祖先元素,一旦祖先元素出现指定的css类/标签时,样式即可生效。在和其他选择器配合使用的过程中,能够带来很高的自由度。

::ng-deep 在shadow DOM中,是用来刺穿样式的,在Angular的视图中,它也起到了相同的作用,使当前组件中定义的样式作用于各级子组件。

ng-zorro中推荐的:host配合上::ng-deep选择器,可以使得样式只影响到当前组件的所有子组件,相对None封装模式带来的全局影响,算是伤害较小的一种。因此在很长一段时间的实践中,我们采用了特殊选择器刺穿的方式。

上面简单介绍了Angular视图封装的一些基础知识,虽然覆盖组件样式暂时达到了目的,终究不是完美的解决办法,期待ng-zorro 7.0 的样式自定义。

以后会持续更新项目开发中积累的一些经验,前后端、运维、团队协作等等。最后为自家产品打个广告,可以快速搭建敏捷开发管理平台工程项目管理等。注册就送30天PRO版本试用~

轻流 · 无需开发,快速搭建业务流程​qingflow.com
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值