探究微信小程序的样式隔离

1,263 阅读4分钟

🤔️在看小程序组件的样式隔离文档的时候,一头雾水,有以下疑问。

1、如何做到父子组件(包括页面和app.wxss)样式可以互相影响,可以单方面影响,也可以完全不影响?

image.png

2、外部样式类是如何实现的,为什么传入的class可以打破样式隔离?

image.png

😎 接下来我们首先分析一下整体的流程,(接下来开始胡扯了)。

app.wxss 与 page的wxss 是如何编译的

我们编写的app.wxss

image.png

我们编写的page的wxss

image.png

话不多说直接调试微信开发者工具。

编译后的app.wxss如下

image.png

编译后的page的wxss如下

image.png

app.wxss和page都是将css直接以style标签的方式插入到head标签内,并且不对css类名做任何修改。

组件的wxss是如何编译的

我们编写的组件wxml

image.png

我们编写的组件wxss

image.png

styleIsolation为isolated

isolated 表示启用样式隔离,在自定义组件内外,使用 class 指定的样式将不会相互影响(一般情况下的默认值)

插入到head中的组件的css

image.png

组件的真实的节点

image.png

styleIsolationisolated时,我们编译后的css会加上前缀,并且在真实节点的class前也会加上前缀。这样做就可以做到app.wxss和page的wxss不会影响到组件的样式了。

styleIsolation为apply-shared

apply-shared 表示页面 wxss 样式将影响到自定义组件,但自定义组件 wxss 中指定的样式不会影响页面

插入到head中的组件的css

image.png

组件的真实的节点

image.png

styleIsolationapply-shared时,需要组件的wxss还是需要加前缀来满足组件的样式不会影响到页面, 但是同时还是希望page的样式来影响到组件,这个就需要在真实节点的class上同时有不带前缀的class和带前缀的class。不带前缀的class是为了匹配page上的样式,带前缀的class是为了匹配组件的样式。

styleIsolation为shared

表示页面 wxss 样式将影响到自定义组件,自定义组件 wxss 中指定的样式也会影响页面和其他设置了 apply-sharedshared 的自定义组件

插入到head中的组件的css

image.png

组件的真实的节点

image.png

在styleIsolation为shared时,其实就是关闭样式隔离,所以 组件的wxss和组件的class都不会加前缀了,同时因为组件的样式晚于页面的样式加载, 所以组件的样式会覆盖掉页面的样式,也会影响到页面元素的样式。

外部样式类

外部样式类解决了什么问题?

小程序支持样式隔离,但是我们在实际开发中还是希望样式可以由外部控制,外部样式类就是解决这个问题,组件与组件之间样式隔离,但是部分样式可以由外部控制。

用法可以参照官方示例: developers.weixin.qq.com/miniprogram…

一句话总结:我们可以将样式class像属性一样传递给子组件,子组件可以直接使用这个class。

那这个是怎么实现的呢?我们先写一个demo

父组件的wxml

image.png

父组件wxss

image.png

子组件js

image.png

子组件wxml

image.png

运行效果

image.png

编译后的结果

image.png 可以和我们编写的子组件wxml进行对比:我们可以发现,微信将我们的 class="parentclass" 替换为了 class="compA--comp-a-clas-a"

结合上文和上述demo可以得知,小程序的样式隔离是通过加前缀的方法来隔离的,也就是说我们只要能拿到加前缀的class就可以用在任何一个组件上。这样我们将声明的externalClasses替换为加前缀的class,这样我们就可以在子组件使用父组件的样式了,同时并没有打破样式隔离。

总结

  1. 小程序的app.css和page的css是没有样式隔离的。意味着子组件只要不开样式隔离,是可以直接使用app.css和page的css的。

  2. 组件是有样式隔离的,由于组件的隔离方案是对class加前缀实现的,这样做的好处是可以通过提供多种隔离方案。

    1. isolated:完全样式隔离,所有class都加前缀。
    2. apply-shared:组件可以使用页面css,同时组件css对页面进行隔离,实现方案是组件的类名会有一个有前缀的class(受组件内部的css控制)、一个没有前缀的class(受页面的css控制)
    3. shared: 关闭隔离方案,所有class都不加前缀。意味着组件和页面的css可以互相影响了。
  3. 外部样式类, 解决了组件开启了组件隔离但是同时部分样式还是希望可以由外部控制的问题。这个实现方案就是通过将声明的externalClasses替换为加前缀的class在传给子组件,子组件就可以使用父组件的class了。