在微信小程序里,自定义组件默认启用了样式隔离,页面中的 class 选择器无法直接作用到组件内部,组件内部的 class 定义也不会外溢到页面或其他组件。这种机制降低了样式冲突的概率,但也带来一个常见问题:当业务需要统一调整卡片、弹窗、表单控件的视觉风格时,页面样式往往不生效。其实小程序并没有把隔离做成二选一的开关,而是提供了 isolated、apply-shared、shared 以及页面级 page-isolated、page-apply-shared、page-shared 六种取值。不同取值决定了样式共享的边界,理解这些差异才能根据业务场景做出合适选择。

一、样式隔离的作用范围与六种取值
样式隔离主要针对 class 选择器。以默认的 isolated 为例,页面 wxss 里写 .container { background: #fff; } 不会影响组件内部带有 container 类名的节点,组件 wxss 里的 .container 也不会泄漏到页面。不过需要特别注意,标签名选择器、部分属性选择器以及 CSS 继承属性并不完全受这套隔离约束。例如页面 wxss 中直接写 view { color: red; } 仍然会穿透到组件内部,因为标签名选择器不属于 class 隔离范围。这一点经常被误解,导致开发者以为样式没有隔离干净。
小程序为 styleIsolation 提供了六种模式:isolated、apply-shared、shared、page-isolated、page-apply-shared、page-shared。前三种在自定义组件的 options 或组件 json 中配置,后三种在页面 json 中配置,用于页面级别的 app.wxss 和组件隔离控制。下表汇总了组件级三种模式的共享方向。
| 模式 | 页面样式影响组件 | 组件样式影响页面 | 适用场景 |
|---|---|---|---|
| isolated | 否 | 否 | 通用基础组件、跨项目组件库 |
| apply-shared | 是 | 否 | 需要继承页面主题的业务组件 |
| shared | 是 | 是 | 与页面强耦合的定制组件 |
页面级取值中的 page-isolated 表示当前页面禁用 app.wxss,并且页面 wxss 与所有自定义组件互不影响;page-apply-shared 同样禁用 app.wxss,但页面 wxss 仍可影响设置了 apply-shared 或 shared 的组件;page-shared 则在禁用 app.wxss 的基础上允许页面样式和组件样式双向流通。这三种模式主要解决全局 app.wxss 对特殊页面产生干扰的问题。
二、组件级三种模式的配置与业务选择
在组件 JS 文件中,可以通过 options.styleIsolation 指定隔离模式。下面的代码让一个业务卡片组件接受页面样式,但不会把自身样式反向传给页面。
Component({
options: {
styleIsolation: 'apply-shared'
},
data: {},
methods: {}
})
也可以在组件 JSON 文件中直接配置 styleIsolation,效果等价。对于纯设计系统组件,例如按钮、输入框、徽标等基础控件,通常保持 isolated。这类组件结构固定,外部不应随意覆盖内部 class,否则同一组件在不同页面会出现视觉不一致。如果产品希望所有按钮都遵循页面或应用的整体皮肤,更好的做法是通过组件 properties 传入主题类型,而不是直接让页面样式覆盖内部结构,这样既保留隔离又能实现定制。
当业务组件需要继承页面背景、字体、颜色等样式时,apply-shared 比较合适。比如一个商品卡片在列表页和详情页需要跟随页面暗色模式,组件内部只定义布局和状态样式,颜色和背景交给页面 wxss 控制。此时组件样式不会反向影响页面,降低了样式外泄风险。若改成 shared,组件内部定义的 .card-title 可能会覆盖页面中同名的元素样式,排查成本会明显增加。
shared 适合组件本身就需要参与页面布局联动或向外部传递样式的场景,例如全局公告栏需要让页面某个容器调整 padding,或者多个组件之间需要共享同一套类名并互相影响。但 shared 是一把双刃剑,一旦组件内部出现与页面同名的类,就会产生意料之外的覆盖。使用 shared 时建议对组件类名增加前缀,同时用注释标明哪些样式会对页面产生影响。
三、页面级隔离与 app.wxss 的特殊处理
页面 json 中的 styleIsolation 与组件级配置解决的问题不同。app.wxss 默认作用于所有页面,但某些活动页、独立工具页不希望继承全局按钮、背景或字体样式。此时可以在页面 json 里设置 page-isolated,一次性禁用 app.wxss,并切断页面 wxss 与组件之间的双向影响。配置方式如下:
{
"usingComponents": {
"custom-card": "/components/custom-card/index"
},
"styleIsolation": "page-isolated"
}
page-apply-shared 和 page-shared 则在禁用 app.wxss 的基础上,重新定义页面与自定义组件的样式共享关系。page-apply-shared 表示页面 wxss 只会影响那些主动设置为 apply-shared 或 shared 的组件,对 isolated 组件仍然无效。这样既能保留全局 app.wxss 之外的页面定制能力,又不会破坏基础组件的隔离性。page-shared 则更激进,允许页面样式与所有支持共享的组件双向影响,适合页面本身就是一个复杂组合组件、需要高度统一调度的场景。
需要注意的是,页面级配置只作用于当前页面,不会跨页面生效。如果多个活动页都需要禁用 app.wxss,可以在每个页面 json 中分别配置。若希望全局自定义组件默认采用某种共享策略,应当优先在组件 options 中统一设置,而不是依赖页面 json 逐个调整。
四、常见误区与选择决策清单
第一个常见误区是认为 styleIsolation 能隔离所有样式。实际上标签名选择器和继承属性仍然可能穿透组件边界。例如在页面 wxss 中写 view { font-size: 14px; },即使组件是 isolated,内部 view 仍然会继承页面字号,因为这是 CSS 继承机制。要彻底避免,需要在组件内部显式设置相关属性。
第二个误区是混用旧字段 addGlobalClass。早期版本中,设置 options.addGlobalClass 为 true 可以让页面样式作用于组件,其效果与 styleIsolation 的 apply-shared 类似。当前开发中建议统一使用 styleIsolation,避免同一组件同时出现两个配置导致维护混乱。第三个误区是在 shared 模式下把组件内部类名起得过于通用,例如 .title、.content、.btn,这类类名很容易与页面样式冲突。
决策时可以先问三个问题:组件是否作为基础组件跨业务复用?如果是,优先 isolated;组件是否需要继承当前页面的主题或布局样式?如果是,优先 apply-shared;组件是否需要向页面传递样式或与其他组件联动?如果是,再考虑 shared。只有当页面本身需要摆脱 app.wxss 影响时,才使用 page-isolated、page-apply-shared 或 page-shared。按照这个顺序筛选,大多数业务场景都能找到明确答案。
最后,样式问题排查时可以在开发者工具中审查元素,查看样式来源是页面 wxss、app.wxss 还是组件 wxss。如果发现样式没有生效,先确认组件当前的 styleIsolation 取值,再检查选择器类型和继承属性。通常把隔离模式调高一级(如从 isolated 改为 apply-shared)能解决页面样式无法覆盖组件的问题,但也要同步评估是否引入新的样式泄漏风险。