如何制作一个可主题化的Angular Material NPM模块?

时间:2018-01-24 16:42:09

标签: javascript angular npm angular-material angular-material2

是否可以构建一个使用Angular Material的npm模块,并允许其定义的组件由消费应用程序的自定义主题设置样式?

作为一个例子,假设我创建了一个包含具有以下模板的组件的npm模块:

<button mat-raised-button color="accent">Click me!</button>

是否可以将此组件导入两个不同的应用程序,每个应用程序定义a custom Angular Material theme,并使按钮采用当前应用程序主题的“重音”颜色?

目前,我正在使用ng-packagr来构建Angular友好的npm模块。但是,据我所知,这个模块包含一个.scss编译阶段作为打包过程的一部分,这意味着模块中定义的任何样式都失去了使用应用程序中的主题自定义的能力。模块。

2 个答案:

答案 0 :(得分:1)

Angular Material Theming Your Own Components指南部分涵盖了如何执行此操作的基本要点。除了主题组件之外,库(“npm模块”)还需要为Angular Material库通过其angular-material-theme() mixin提供的所有样式提供入口点。这通常通过定义一个mixin来定义样式并调用所有组件主题mixins来完成,而不是创建一个带样式定义的样式表文件。 mixin将主题作为参数,并使用该主题定义其自己的所有样式以及将其应用于其任何组件。例如,您的库可能有自己的_theme.scss文件,任何消费应用程序都可以导入该文件,这将定义mixin:

@import '~@angular/material/theming';
@import './components/my-component/_my-component-theme'; // component theming file with mixin
@mixin library-theme($theme) {

    @include angular-material-theme($theme); // angular material

    @include my-component-theme($theme); // component theming

    // define non-component styles
}

消费应用程序需要导入库的主题文件,创建自己的主题,然后调用库的主题混合。

显然有更多细节,但这些是基础知识。作为参考,我建议您通过GitHub查看Angular Material如何自己的theming

答案 1 :(得分:1)

确实,这是可能的。这个问题与Angular无关,它适用于那里的任何其他框架。

在此之前,您需要了解依赖倒置的概念。假设您正在构建应用 App1 App2 ,并使用包含可重用组件的npm模块 lib 。您的应用程序构建在 lib 之上,这意味着您的应用程序是更高级别的模块, lib 是更低级别的模块。

如果您认为lib是自包含的,那么理想情况下,它应该与App1App2中使用的相同。但是你的要求是 - lib 应该根据应用程序有不同的行为(在这种情况下为样式)。这意味着您希望更高级别的模块就较低级别模块的行为方式做出一些决定。所以你正在反转依赖,那就是依赖倒置原则。详细了解DIP on wikipedia

现在要实现DIP,您需要从库中公开某种端口/扩展,并且出于样式目的,最简单的方法是公开SCSS mixins 。但是如果您使用任何构建工具(如Webpack,汇总或ng-package),那么它们将始终生成已编译的分发。您将不得不编写一些额外的node.js脚本来打包源代码(此处为SCSS)以及已编译的代码。这些脚本将在编译/捆绑步骤中执行。

在我的工作中,我有类似的要求。您应该遵循一些指导原则:

  1. 库中的组件应该开箱即用,并带有一些默认样式。
  2. 默认情况下,库的用户不必每次都自定义组件。
  3. 从样式组件中公开mixins。
  4. 在mixins中,不要放任何硬编码的首选项。
  5. 开发主题组件时,请从默认开始。覆盖应用程序中组件使用的默认CSS类。清空公共自定义点/属性,然后将其放回到库的下一个版本中。不要在库中进行前期开发。它通常会导致返工。
  6. 我们有一个企业级应用程序。共有5个不同的应用程序和一个私有发布的npm模块,为所有这五个应用程序提供公共组件。但是有一些组件需要采用不同的样式,正如我所说的,首先在我们的应用程序中覆盖类,然后一旦感觉通用到足以放入通用模块,我们就把它放在下一个版本中。