样式共享与隔离

全局样式

在根目录下有一个app.wxss,该文件用于放置全局样式,写在这里面的样式将影响所有页面及组件(配置了样式隔离的除外)

页面样式

有三种隔离模式,isolated(默认),apply-shared,shared

Page({
  options: {
    styleIsolation: 'isolated',
  }
})

个人经验

一般第三方组件都会设置apply-shared,以便于页面实现样式覆盖,这里注意,只有页面可以实现样式覆盖,组件不行

在自定义组件中用了另一个组件(例如第三方的vant),如果想要实现样式覆盖,则需要是用shared,但是使用shared后容易使得页面的其他组件也被影响,所以最佳实践是在进行样式覆盖的时候,将覆盖的样式控制在某个元素中。

如需要覆盖.van-popup,则在使用组件的外围包裹一层view,最终的覆盖样式应该是如下:

.shops .van-popup {
  background-color: #fff !important;
}

.shops 是外围view的class

<view class="shops">
  <van-popup></van-popup>
</view>

原理猜测

当打开(或者编译?)时,以page为单位,将所有组件的样式根据隔离选项重新进行合并生成

方式是,先根据自定义组件的隔离方式从下往上传递,然后再根据自定义组件的隔离方式从上往下传递

举个例子,页面上有自定义组件A、组件B、组件C、组件D

组件A是isolated

组件B是apply-shared

组件C是shared

组件D是shared

首先是从下往上传递,那么Page的样式=组件C+组件D+Page

接着是从上往下传递,那么

最终组件A = 组件A

最终组件B = 最终Page样式+组件B =  组件C+组件D+Page+组件B (也就是 组件C,组件D以及页面的样式都会影响组件B)

最终组件C = 最终Page样式 = 组件C+组件D+Page(也就是 组件D以及页面的样式都会影响组件C)

最终组件D= 最终Page样式= 组件C+组件D+Page(也就是 组件C以及页面的样式都会影响组件D)


下面是一些官方的文档片段

styleIsolation 选项从基础库版本 2.6.5 开始支持。它支持以下取值:

  • isolated 表示启用样式隔离,在自定义组件内外,使用 class 指定的样式将不会相互影响(一般情况下的默认值);
  • apply-shared 表示页面 wxss 样式将影响到自定义组件,但自定义组件 wxss 中指定的样式不会影响页面;
  • shared 表示页面 wxss 样式将影响到自定义组件,自定义组件 wxss 中指定的样式也会影响页面和其他设置了 apply-sharedshared 的自定义组件。(这个选项在插件中不可用。)

使用后两者时,请务必注意组件间样式的相互影响。

如果这个 Component 构造器用于构造页面 ,则默认值为 shared ,且还有以下几个额外的样式隔离选项可用:

  • page-isolated 表示在这个页面禁用 app.wxss ,同时,页面的 wxss 不会影响到其他自定义组件;
  • page-apply-shared 表示在这个页面禁用 app.wxss ,同时,页面 wxss 样式不会影响到其他自定义组件,但设为 shared 的自定义组件会影响到页面;
  • page-shared 表示在这个页面禁用 app.wxss ,同时,页面 wxss 样式会影响到其他设为 apply-sharedshared 的自定义组件,也会受到设为 shared 的自定义组件的影响。

从小程序基础库版本 2.10.1 开始,也可以在页面或自定义组件的 json 文件中配置 styleIsolation (这样就不需在 js 文件的 options 中再配置)。例如:

{
  "styleIsolation": "isolated"
}

此外,小程序基础库版本 2.2.3 以上支持 addGlobalClass 选项,即在 Componentoptions 中设置 addGlobalClass: true 。 这个选项等价于设置 styleIsolation: apply-shared ,但设置了 styleIsolation 选项后这个选项会失效。