Angular Material 18 中 mat.define-palette 报错的解决方法
问题描述
升级到 Angular Material 18 后,在编译过程中遇到以下 Sass 错误:
X [ERROR] Undefined function.
╷
14 │ $myapp-theme-primary: mat.define-palette(mat.$indigo-palette, A400, A100, A700);
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
这个错误发生在 styles.scss
文件中,具体位置是定义主题调色板的地方。错误信息明确指出 define-palette()
函数未定义。该问题在从 Angular Material 17 升级到 18 后出现,即使使用官方推荐的 ng update @angular/material
更新命令也可能发生。
典型的问题场景包括:
- 升级后主题定义代码未被自动迁移
- 使用 Angular Material 18 时尝试调用旧的 API 函数
- 编译时在主题生成阶段出现 Sass 函数未定义的错误
注意
自动迁移工具可能无法完全处理主题文件中的自定义配置。如果主题文件未被修改过,升级工具可能默认这些文件已迁移,但实际上需要手动调整。
错误原因
Angular Material 18 引入了一项重大更新:Material Design 2(M2)API 已被弃用,取而代之的是 Material Design 3(M3)API。这些变更在 Angular Material 18 官方更新说明 的 "Breaking Changes" 部分中有详细说明。
被移除的 API
这些 API 在 Angular Material 18 中已被移除:
define-palette()
define-light-theme()
$indigo-palette
- 其他以
define-*
开头的主题构建函数
完整解决方案
代码重构步骤
修改您的主题定义文件(通常是 styles.scss
),应用以下变更:
// 旧的 v17 代码(已废弃) ❌
$myapp-theme-primary: mat.define-palette(mat.$indigo-palette, A400, A100, A700);
// v18 修复代码 ✅
$myapp-theme-primary: mat.m2-define-palette(mat.$m2-indigo-palette, A400, A100, A700);
以下是完整的修复代码:
// 导入 Material 库
@use '@angular/material' as mat;
@include mat.core();
// v18 兼容的主题定义
$myapp-theme-primary: mat.m2-define-palette(mat.$m2-indigo-palette, A400, A100, A700);
$myapp-theme-accent: mat.m2-define-palette(mat.$m2-indigo-palette);
$myapp-theme-warn: mat.m2-define-palette(mat.$m2-red-palette);
// 使用新前缀函数定义主题
$myapp-theme: mat.m2-define-light-theme((
color: (
primary: $myapp-theme-primary,
accent: $myapp-theme-accent,
warn: $myapp-theme-warn,
)
));
// 应用主题
@include mat.all-component-themes($myapp-theme);
具体变更说明
函数前缀:
define-palette()
→m2-define-palette()
define-light-theme()
→m2-define-light-theme()
调色板变量:
$indigo-palette
→$m2-indigo-palette
$red-palette
→$m2-red-palette
命名一致性:
- 所有函数和变量需统一使用
m2-
前缀 - M3 使用
m3-
前缀(如果您正在迁移到 Material Design 3)
- 所有函数和变量需统一使用
Material 2 与 Material 3 的选择
- m2-前缀:保持 Material Design 2 样式和视觉风格的解决方案
- m3-前缀:若需迁移到 Material Design 3,需使用
m3-define-palette()
并进行全面设计调整
继续使用 M2 API(使用 m2-
前缀)可最小化升级工作,保持现有设计风格。
验证方案
- 运行编译命令:
ng serve
- 预期结果:
- 编译成功完成
- Sass 错误不再出现
- 应用主题渲染正常,颜色配置保持不变
常见问题解决
更新后仍有报错
确认主题文件中是否遗漏了部分需要替换的函数名。使用 "查找并替换" 操作确保所有 define-palette
已被替换为 m2-define-palette
。
部分组件样式异常
尝试执行完整的构建缓存清理:
ng clean # 清理构建缓存
rm -rf node_modules/.cache # 删除 Sass 编译缓存
npm install # 重新安装依赖
自定义调色板的问题
如果您创建过自定义调色板(如 my-custom-palette
),需在定义时添加 m2-
前缀:
// 自定义调色板定义
$my-custom-palette: mat.m2-define-palette(...);
// 在主题中使用
$theme: mat.m2-define-light-theme((
color: (primary: $my-custom-palette)
));
迁移建议
- 优先使用官方更新工具:
ng update @angular/material
升级后检查主题文件: 即使自动迁移成功,也应手动确保所有主题相关代码使用了新的
m2-
API。考虑迁移到 Material Design 3: 虽然本方案保持 M2 设计风格,Angular Material 18 完全支持 M3 设计体系。迁移到 M3 需要更大的设计调整:
// Material Design 3 主题配置 (可选)
$theme: mat.define-theme((
color: (
theme-type: light,
primary: mat.$violet-palette
)
));
未来演进方向
Angular 团队计划在未来的版本中移除对 Material Design 2 API 的兼容层(m2-
前缀)。从 v18 开始,建议优先考虑 Material Design 3 的设计方案。