如何在Angular Material中制作自定义主题

by Charlee Li

通过李李

如何在Angular Material中制作自定义主题 (How to make a custom theme in Angular Material)

Angular Material is a great library that implements Material Design for Angular 2+. The official document is sufficient regarding the component usages, while there are few articles about how to customize the theme itself, specifically, the colors used in the theme.

Angular Material是一个很棒的库,可实现Angular 2+的Material Design 。 关于组件用法的官方文档就足够了,而关于如何自定义主题本身(特别是主题中使用的颜色)的文章很少。

In this post I would like to summarize what I’ve learned these months from customizing Angular Material themes.

在这篇文章中,我想总结一下这几个月来我从定制Angular Material主题中学到了什么。

Note this article is NOT about AngularJS Material, which is used for AngularJS 1.x.

请注意,本文与用于AngularJS 1.x的 AngularJS材质 无关

Some common posts about customizing themes are:

有关定制主题的一些常见文章是:

I didn’t find other useful posts and would appreciate if anyone could provide some resources in the comments.

我没有找到其他有用的帖子,如果有人可以在评论中提供一些资源,我将不胜感激。

如何创建自定义主题 (How to Create a Custom Theme)

Creating a material theme is extremely simple: you only need to pick three colors — primary, accent, and warn — and Angular Material will do the rest for you. The material palette page explains how it works clearly, and you can also create a theme visually with Color Tool.

创建材质主题非常简单:您只需选择三种颜色( 色, 强调色和警告色),而Angular Material会为您完成其余工作。 材质调色板页面说明了其清晰的工作原理,您还可以使用Color Tool直观地创建主题。

In regards to code, all you need to do is to create the following theme file:

关于代码,您需要做的就是创建以下主题文件:

// theme.scss@import '~@angular/material/theming';
$my-theme-primary: mat-palette($mat-green);$my-theme-accent : mat-palette($mat-amber);$my-theme-warn   : mat-palette($mat-red);
$my-theme: mat-light-theme(    $my-theme-primary,    $my-theme-accent,    $my-theme-warn);

Then you need to apply this theme in your main style.scss file:

然后,您需要在主style.scss文件中应用此主题:

@import "theme.scss";
@include mat-core();@include angular-material-theme($my-theme);

如何在组件中使用自定义主题 (How to Use Custom Theme in Components)

After creating our own theme, requirements like this will rise:

创建我们自己的主题后,将产生如下要求:

I want to create a text box. The text color, background color, and border color should all come from our own theme, not by hard coding.
我想创建一个文本框。 文字颜色,背景颜色和边框颜色都应来自我们自己的主题,而不是硬编码。

This requirement is pretty common — anyway, being able to be used in components is exactly why we want to create a custom theme. The problem is how.

这项要求很常见-无论如何,能够在组件中使用正是我们想要创建自定义主题的原因。 问题是如何。

混合方法 (The mixin approach)

The first official document I shared proposed a way of using SCSS’s mixin. I call it a “bottom-up” approach, which includes the following steps:

我共享的第一份正式文档提出了一种使用SCSS的mixin的方法。 我称之为“自下而上”的方法,其中包括以下步骤:

  1. Each component defines a theme mixin, and retrieves colors from $theme parameter.

    每个组件都定义一个主题混合,并从$theme参数检索颜色。

  2. A global theme.scss defines the custom theme, then includes all the component theme mixins and calls them with the custom theme.

    全局theme.scss定义了自定义主题,然后包括所有组件主题mixins并使用自定义主题对其进行调用。

In addition to the theme.scss definition mentioned above, each component needs to create a theme file like this:

除了上面提到的theme.scss定义外,每个组件还需要创建一个主题文件,如下所示:

// src/app/comp-a/comp-a.theme.scss@import '~@angular/material/theming';
@mixin comp-a-theme($theme) {          // define mixin  $primary: map-get($theme, primary);  // retrieve color def  button {                             // apply theme to component    background-color: mat-color($primary);  }}

And probably you want a custom-theme.scss to import all the component level themes:

可能您希望custom-theme.scss导入所有组件级主题:

// src/app/custom-theme.scss@import '~@angular/material/theming';@import 'src/app/comp-a/comp-a.theme';@import 'src/app/comp-b/comp-b.theme';
@mixin custom-themes($theme) {  @include comp-a-theme($theme);  @include comp-b-theme($theme);}

Then import the above custom-theme.scss in your theme.scss:

然后将上面的custom-theme.scss导入您的theme.scss

// theme.scss...@import './custom-theme';@include custom-themes($my-theme);

This hierarchy works, and probably is the only way when you need to support multiple themes.

这种层次结构有效,并且可能是您需要支持多个主题的唯一方法。

However, most of the time we only support one theme, and using a mixin could be cumbersome. Mainly there are three disadvantages with this approach:

但是,大多数时候我们只支持一个主题,使用mixin可能很麻烦。 这种方法主要存在三个缺点:

  1. Every single color reference needs a separate .theme.scss file.

    每个单色参考都需要一个单独的.theme.scss文件。

  2. custom-theme.scss must know exactly which components provide custom themes. This creates unnecessary dependencies.

    custom-theme.scss必须准确知道哪些组件提供了自定义主题。 这将创建不必要的依赖关系。

  3. Most importantly, component level theme files are not encapsulated.

    最重要的是,未封装组件级主题文件。

The first and second points are pretty self-explanatory. Let me explain a little bit about point 3. This involves some background knowledge called “View Encapsulation”.

第一点和第二点很不言而喻。 让我对点3进行一些解释。这涉及一些称为“视图封装”的背景知识。

Angular uses a technique called “View Encapsulation” to keep component CSS local. In other words, rules defined for one component will stay in that component and will not affect other components.

Angular使用一种称为“ 视图封装 ”的技术将组件CSS保持在本地 。 换句话说,为一个组件定义的规则将保留在该组件中,并且不会影响其他组件。

In this way you can define CSS class name freely in your component without worrying about naming conflicts. However, view encapsulation is done only if the CSS is defined through @Component, i.e. @Component({ styleUrls: ['./comp-a.scss'] }).

这样,您可以在组件中自由定义CSS类名,而不必担心命名冲突。 但是,仅在通过@Component定义CSS的情况下才进行视图封装,即@Component({ styleUrls: ['./comp-a.scss'] })

As to our custom theme file comp-a.theme.scss, since it is imported directly by custom-theme.scss, its rules are not encapsulated so it will apply to all elements on the page. In the example above, I used the following code (which was WRONG!):

至于我们的自定义主题文件comp-a.theme.scss ,由于它是由custom-theme.scss直接导入的,因此其规则未封装,因此将适用于页面上的所有元素。 在上面的示例中,我使用了以下代码(错误!):

@mixin comp-a-theme($theme) {  button { ... }    // This will apply to ALL buttons!}

But this will apply the style to all the buttons instead of those buttons belonging to comp-a only. You have to do something like comp-a button in order to make this work correctly.

但这会将样式应用于所有按钮,而不是仅属于comp-a的那些按钮。 您必须执行诸如comp-a button的操作才能使其正常工作。

直接方法 (The direct approach)

Therefore I propose a better approach. Instead of using a mixin, we let each component include the theme file and use the color definition directly.

因此,我提出了一种更好的方法。 让每个组件都包括主题文件并直接使用颜色定义,而不是使用mixin。

In this approach, the component theme file will look like this:

用这种方法,组件主题文件将如下所示:

// NOTE: just do this in your regular scss file.// No need to create separate theme file!// src/app/comp-a/comp-a.scss@import 'src/theme.scss';
$primary: map-get($my-theme, primary);button {  background-color: mat-color($primary);}

And that’s all.

就这样。

Let’s see how this works. First, theme related rules are put into the component SCSS file, so no extra component level theme file required. Second, the main theme.scss does not need to know component level themes (since it does not need to import them), so a simple theme definition is adequate. Third, the component SCSS file is used with @Component so it is encapsulated correctly, which means we can simply define rules for button.

让我们看看它是如何工作的。 首先,将与主题相关的规则放入组件SCSS文件中,因此不需要额外的组件级主题文件。 其次,主theme.scss不需要知道组件级主题(因为它不需要导入它们),因此简单的主题定义就足够了。 第三,组件SCSS文件与@Component使用,因此它被正确封装,这意味着我们可以简单地为button定义规则。

预定义的主题键 (Predefined Theme Keys)

Probably you have noticed the next problem. What are the foreground, primary in above theme files ( map-get($my-theme, primary))? Are there any other keys I can use?

可能您已经注意到下一个问题。 上面的主题文件( map-get($my-theme, primary) )中的foregroundprimary是什么? 我还能使用其他任何键吗?

Well these “keys” refer to different colors defined in the theme. However I could not find any documents explaining these “keys”, so the only way I could find out is to read the source code. (Although it is said that good programmers should read the code, having to read the code is definitely not a good sign for a library.)

这些“键”指的是主题中定义的不同颜色。 但是,我找不到解释这些“键”的任何文档,所以我唯一能找到的方法就是阅读源代码 。 (尽管据说好的程序员应该阅读代码, 但是必须阅读代码绝对不是一个好的库。)

Open node_modules/@angular/material/_theming.scss and you will see the definitions for these keys. For future reference, I would like to summarize the keys here.

打开node_modules/@angular/material/_theming.scss ,您将看到这些键的定义。 为了将来参考,我想在这里总结一下按键。

$theme  |- primary  |- accent  |- warn  |- foreground  |   |- base  |   |- divider  |   |- dividers  |   |- disabled  |   |- disabled-button  |   |- disabled-text  |   |- hint-text  |   |- secondary-text  |   |- icon  |   |- icons  |   |- text  |   |- slider-min  |   |- slider-off  |   `- slider-off-active  |- background  |   |- status-bar  |   |- app-bar  |   |- background  |   |- hover  |   |- card  |   |- dialog  |   |- disabled-button  |   |- raised-button  |   |- focused-button  |   |- selected-button  |   |- selected-disabled-button  |   |- disabled-button-toggle  |   |- unselected-chip  |   `- disabled-list-option  `- is-dark         // bool, whether dark theme or not

For example, if you want to render a disabled text in your component, you may want to use the following code:

例如,如果要在组件中呈现禁用的文本,则可能需要使用以下代码:

$foreground: map-get($my-theme, foreground);.disabled-text {  color: mat-color($foreground, disabled-text);}

Okay these are some lessons I’ve learned from struggling with Angular Material. Hope this post is helpful if you are facing similar problems.

好的,这些是我从Angular Material的努力中学到的教训。 如果您遇到类似的问题,希望这篇文章对您有所帮助。

翻译自: https://www.freecodecamp.org/news/how-to-make-a-custom-theme-in-angular-material-d47122a1e361/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值