Skip to content

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 中已被移除:

  1. define-palette()
  2. define-light-theme()
  3. $indigo-palette
  4. 其他以 define-* 开头的主题构建函数

完整解决方案

代码重构步骤

修改您的主题定义文件(通常是 styles.scss),应用以下变更:

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);

以下是完整的修复代码:

scss
// 导入 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);

具体变更说明

  1. 函数前缀

    • define-palette()m2-define-palette()
    • define-light-theme()m2-define-light-theme()
  2. 调色板变量

    • $indigo-palette$m2-indigo-palette
    • $red-palette$m2-red-palette
  3. 命名一致性

    • 所有函数和变量需统一使用 m2- 前缀
    • M3 使用 m3- 前缀(如果您正在迁移到 Material Design 3)

Material 2 与 Material 3 的选择

  • m2-前缀:保持 Material Design 2 样式和视觉风格的解决方案
  • m3-前缀:若需迁移到 Material Design 3,需使用 m3-define-palette() 并进行全面设计调整

继续使用 M2 API(使用 m2- 前缀)可最小化升级工作,保持现有设计风格。

验证方案

  1. 运行编译命令
bash
ng serve
  1. 预期结果
  • 编译成功完成
  • Sass 错误不再出现
  • 应用主题渲染正常,颜色配置保持不变

常见问题解决

更新后仍有报错

确认主题文件中是否遗漏了部分需要替换的函数名。使用 "查找并替换" 操作确保所有 define-palette 已被替换为 m2-define-palette

部分组件样式异常

尝试执行完整的构建缓存清理:

bash
ng clean  # 清理构建缓存
rm -rf node_modules/.cache  # 删除 Sass 编译缓存
npm install  # 重新安装依赖

自定义调色板的问题

如果您创建过自定义调色板(如 my-custom-palette),需在定义时添加 m2- 前缀:

scss
// 自定义调色板定义
$my-custom-palette: mat.m2-define-palette(...);

// 在主题中使用
$theme: mat.m2-define-light-theme((
  color: (primary: $my-custom-palette)
));

迁移建议

  1. 优先使用官方更新工具
bash
ng update @angular/material
  1. 升级后检查主题文件: 即使自动迁移成功,也应手动确保所有主题相关代码使用了新的 m2- API。

  2. 考虑迁移到 Material Design 3: 虽然本方案保持 M2 设计风格,Angular Material 18 完全支持 M3 设计体系。迁移到 M3 需要更大的设计调整:

scss
// 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 的设计方案。