Material Components Web 架构解析:包划分、Sass 体系与 Foundation/Adapter 分层设计
2026/9/21 15:17:41 网站建设 项目流程
  • 前端
  • UI组件
  • 设计系统

【免费下载链接】material-components-web

Modular and customizable Material Design UI components for the web

项目地址:https://gitcode.com/gh_mirrors/ma/material-components-web
点击查看免费下载

本篇技术指南基于仓库中的 architecture.md 核心文档,深入剖析 Material Components Web(MDC Web)的整体架构:它如何通过 Subsystem/Component 的包划分组织代码,如何用 Sass mixin 复用样式,以及如何以 Foundation/Adapter 分层把业务逻辑与 DOM 彻底解耦,从而支持在 React、Angular 等不同框架间复用同一套组件逻辑。读完本文,你将掌握 MDC Web 的源码组织方式、组件三件套(Component / Foundation / Adapter)的协作关系,以及作为普通消费方应该只与哪一层 API 交互。

总体架构:Subsystem 与 Component 的包划分

MDC Web 将整个代码库拆分为一个个独立的packages/目录(npm 包),每个包要么是一个Subsystem(子系统),要么是一个Component(组件)

  • Subsystem(子系统):被多个组件复用的基础能力,通常描述样式(例如颜色,见 mdc-theme)或动效(例如动画与缓动曲线,见 mdc-animation 及其 README 中提供的$standard-curve-timing-function等 Sass 变量)。
  • Component(组件):面向用户的具体 UI 部件(如 Button、Checkbox、Dialog、Snackbar 等),趋向于依赖多个子系统包,但很少依赖其他组件包。例如按钮包的 package.json 依赖了@material/density@material/dom@material/elevation@material/feature-targeting@material/focus-ring@material/ripple@material/rtl@material/shape@material/theme@material/tokens@material/touch-target@material/typography等十余个子系统,但并没有依赖 checkbox、dialog 之类的组件包。

这种依赖方向保证了架构的核心约束,也是原文档强调的第一条设计原则:

每个组件都可以独立于其他任何组件单独使用(Each component is usable separate from any other component)。

从代码上看,每个组件包的结构高度一致:以 mdc-checkbox 为例,包含component.ts(Vanilla 组件)、foundation.ts(Foundation)、adapter.ts(Adapter 接口)、constants.ts(cssClasses/strings/numbers 常量)、index.ts(导出入口)以及一系列_*.scss样式文件,这为"按需引入单个组件"提供了天然的物理边界。

Sass:以 mixin 复用的样式体系

MDC Web 的全部 CSS 都由Sass生成。原文档指出:

  • Sassmixin让开发者可以把一组可复用的 CSS 声明组织起来,应用到多个组件上;
  • 子系统提供 Sass mixin,组件在自己的 Sass 文件中导入这些 mixin;
  • 每个包将自己的 Sass 文件编译为一个单独的 CSS 文件

这一模式在源码中可以直接验证。按钮的基础样式文件 _button-base.scss 顶部集中@use了 elevation、feature-targeting、ripple-theme、rtl、dom、touch-target、focus-ring、typography 等多个子系统模块,并定义static-styles($query)这类 mixin 来组装.mdc-button的结构样式;而 _index.scss 只做了一件事——@forward './button-theme',把主题 mixin 转发给使用方。也就是说,组件的样式文件是"子系统 mixin 的组装车间",每个组件最终产出一个独立的 CSS 文件,配合@use "@material/button"即可引入。

借助@material/feature-targeting子系统,mixin 还支持按structurecolor等目标(query)按需产出样式,实现"只编译用到的部分",这是 MDC Web 样式体系可定制、可裁剪的关键机制。

HTML:不提供模板,只提供结构文档

原文档明确声明:

MDC Web 不提供任何 HTML 模板(MDC Web does NOT provide any HTML templates)。我们只是在文档中给出所需的 HTML 结构。

这意味着 MDC Web 与"开箱即用、带完整 DOM 骨架"的 UI 库不同:使用方需要按照各组件 README 中给出的结构自己编写 HTML(例如 checkbox 组件要求的.mdc-checkbox包裹结构与原生<input type="checkbox">),再引入对应的 CSS 与 JS 完成升级(upgrade)。该策略让组件样式与业务 DOM 完全解耦,也为接入各种框架(通过模板/JSX 渲染 DOM)留下了空间。

JavaScript 分层设计:Foundation / Adapter / Vanilla Component

为什么拆分 Foundation 与 Adapter

MDC Web 把每个动态组件的 JavaScript 拆成两半:**Foundation(基座)**与Adapter(适配器)。这样做的直接收益是:

我们可以在多个 Web 平台(例如 React 和 Angular)上复用 Foundation 代码,只需要重新实现 Adapter 即可。目前我们只实现了 Adapter 的 vanilla JavaScript 版本。

也就是说,组件中"最接近 Material Design 规范"的那部分逻辑只写一次(Foundation),平台相关的那部分(DOM 读写、事件监听等)通过接口(Adapter)隔离,换平台只换 Adapter。这一"业务内核 + 平台适配"的思路,是 MDC Web 能被各类框架封装(wrapper)复用的根本原因。

TypeScript 与发布产物

MDC Web 组件使用 TypeScript 编写,以提升开发效率并减少错误。npm 发布产物包括:

  • UMD JavaScript bundlespackage.jsonmain指向 dist 下的 UMD 模块,兼容性最好);
  • ES Modules(仅含 ES5 语法,配合module字段供 Webpack/Rollup 等工具做 tree-shaking);
  • .d.ts类型声明文件(供 TypeScript 用户消费,编译器通过types字段自动发现)。

具体的导入方式(ES Modules、CommonJS、AMD、Global/CDN 以及document.querySelectorAll批量实例化)详见 导入 JS 指南。

Foundation:不含 DOM 引用的业务逻辑

Foundation 承载"最能代表 Material Design 的业务逻辑",但不直接引用任何 DOM 元素;凡是需要操作 DOM 的逻辑,都委托给 Adapter 方法完成。从基类 foundation.ts 可以看到这套设计:

  • MDCFoundation<AdapterType>构造函数接收 adapter(默认空对象);
  • 提供静态 gettercssClassesstringsnumbers用于导出组件所需的 CSS 类、语义字符串和数字常量;
  • 提供init()destroy()钩子,分别执行初始化和反初始化例程(如注册/注销事件)。

以 checkbox 为例,MDCCheckboxFoundation 覆盖了这些静态 getter,并在构造时用{...MDCCheckboxFoundation.defaultAdapter, ...adapter}将调用方传入的(可能是部分的)adapter 与默认空实现合并,保证任何时刻 Foundation 调用的 adapter 方法都有兜底;它的setDisabled(disabled)就直接调this.adapter.setNativeControlDisabled(disabled),而不是触碰 DOM。

Adapter:框架无关的接口契约

Adapter 是"Foundation 实现 Material Design 业务逻辑所需的全部方法的接口",可以有多个实现,从而实现与不同框架的互操作。每个组件的 adapter 接口都定义在独立的adapter.ts中。例如 MDCCheckboxAdapter 声明了addClassforceLayouthasNativeControlisAttachedToDOMisCheckedisIndeterminateremoveClassremoveNativeControlAttrsetNativeControlAttrsetNativeControlDisabled等方法——这些正是复选框的选中态、不确定态、禁用态、动画同步等业务逻辑所需的全部"能力点"。

Vanilla Component:默认实现与 getDefaultFoundation

Vanilla Component 以根元素(rootElement)实例化,它通过覆盖基类MDCComponentgetDefaultFoundation方法,创建"Foundation 实例 + Vanilla Adapter"的组合;Vanilla Adapter 实现 Adapter 接口并直接引用根元素;同时 Vanilla Component 还会为开发者需要访问的 Foundation 方法暴露代理方法(proxy)。

从基类 component.ts 可以看清组件实例化的完整流程:

  1. 构造函数接收root与可选的foundation,先调用initialize(...args)(子类可在此做构造期准备);
  2. 若未显式传入 foundation,则调用getDefaultFoundation()生成——基类默认实现会直接抛错,强制子类覆盖(component.ts#L73-L80);
  3. 调用this.foundation.init()初始化 Foundation;
  4. 调用initialSyncWithDOM()让组件与宿主 DOM 同步(例如在根元素上注册changeanimationend事件监听,见 checkbox component.ts#L99-L110);
  5. destroy()时依次执行清理,并调用this.foundation.destroy()

基类还提供了listen/unlisten事件封装与emit自定义事件发射方法,组件在需要时也会在自身之上组合其他子系统组件(例如 checkbox 组合了MDCRipple实现水波纹反馈)。

面向消费方的结论

原文档对使用方式给出了非常明确的分工建议:

只想消费 MDC Web(而不是提供封装库)的开发者,只需与 Component 交互,不需要直接访问 Foundation 或 Adapter 的 API。

这也正是各组件 README 中new MDCCheckbox(document.querySelector('.mdc-checkbox'))这类用法的由来——日常使用只面对 Component 这个门面。

组件间的依赖规则与整体组装

汇总包 material-components-web/index.ts 展示了"组件互不依赖、由聚合层统一编排"的最终形态:它把 banner、checkbox、chips、data-table、dialog、drawer、menu、select、slider、snackbar、tab、textfield、tooltip、top-app-bar 等组件统一注册到autoInit(通过data-mdc-auto-init属性自动初始化),并把它们全部导出。也就是说,单组件可独立使用,整套引入则由聚合包完成。

结合前文可见,MDC Web 架构的核心是三条清晰的分层规则:

  1. 包层面:Subsystem 提供基础能力,Component 依赖 Subsystem,组件之间彼此独立;
  2. 样式层面:Sass mixin 复用 + 每包单一 CSS 输出,支持按需裁剪;
  3. 逻辑层面:Foundation(纯业务)— Adapter(接口契约)— Vanilla Component(默认实现)三段式,让业务内核跨框架复用成为可能。

延伸阅读

  • 导入 JS 组件指南:ES Modules / CommonJS / AMD / CDN 四种导入方式与批量实例化写法
  • 架构文档原文
  • 基础包源码:component.tsfoundation.ts基类实现
  • 复选框示例:adapter.ts/foundation.ts/component.ts三件套的完整参照
  • 按钮包依赖清单:组件依赖子系统包的实际证据
  • 前端
  • UI组件
  • 设计系统

【免费下载链接】material-components-web

Modular and customizable Material Design UI components for the web

项目地址:https://gitcode.com/gh_mirrors/ma/material-components-web
点击查看免费下载
上一篇:ChatTTS-ui 音色定制保姆级教程:3步选音色、导入音色文件、加上情绪效果
下一篇:10分钟掌握Sentry性能分析:从卡顿到丝滑的用户体验优化指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询