Hogyan készítsünk egyedi témát a szögletes anyagból

Az Angular Material egy nagyszerű könyvtár, amely megvalósítja az Angular 2+ anyagtervezését. A hivatalos dokumentum elegendő az összetevők használatával kapcsolatban, míg kevés cikk szól arról, hogyan lehet testre szabni magát a témát, konkrétan a témában használt színeket.

Ebben a bejegyzésben szeretném összefoglalni, mit tanultam ezekben a hónapokban az Angular Material témák testreszabásával.

Vegye figyelembe, hogy ez a cikk NEM szól az AngularJS 1.x-hez használt AngularJS anyagról.

Kapcsolódó hozzászólások

Néhány gyakori bejegyzés a témák testreszabásáról:

  • „Az Ön szögletes anyagának alkalmazása”, az egyedi témák hivatalos útmutatója,
  • Tomas Trajan „A teljes útmutató a szögletes anyag témáihoz”, amely sok dokumentálatlan utasítást tartalmaz. Erősen ajánlott .

Nem találtam más hasznos bejegyzést, és nagyra értékelném, ha valaki tudna valamilyen forrást megadni a megjegyzésekben.

Egyéni téma létrehozása

Anyagi téma létrehozása rendkívül egyszerű: csak három színt kell választania - az elsődleges , az akcentust és a figyelmeztetést - és a szögletes anyag megteszi a többit az Ön számára. Az anyagpaletta oldal elmagyarázza, hogyan működik egyértelműen, és a Színes eszközzel vizuálisan is létrehozhat egy témát.

Ami a kódot illeti, mindössze annyit kell tennie, hogy létrehozza a következő téma fájlt:

// [email protected] '[email protected]/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);

Ezután ezt a témát kell alkalmaznia a fő style.scssfájlban:

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

Az egyéni téma használata az alkatrészekben

Saját téma létrehozása után az ehhez hasonló követelmények emelkedni fognak:

Szeretnék létrehozni egy szövegdobozt. A szöveg színének, háttérszínének és szegélyének színének mind a saját témánkból kell származnia, nem kemény kódolással.

Ez a követelmény meglehetősen gyakori - egyébként is, ha komponensekben lehet használni, pontosan ezért akarunk egyedi témát létrehozni. A probléma az, hogyan.

A mixin megközelítés

Az első hivatalos dokumentum, amelyet megosztottam, az SCSS keverékének használatát javasolta. „Alulról felfelé építkező” megközelítésnek nevezem, amely a következő lépéseket tartalmazza:

  1. Minden komponens meghatároz egy témakombinációt, és lekéri a színeket a $themeparaméterből.
  2. A globális theme.scssmeghatározza az egyéni témát, majd tartalmazza az összes komponens témakombinációt, és meghívja őket az egyéni témával.

A theme.scssfent említett definíción kívül minden komponensnek létre kell hoznia egy ilyen témájú fájlt:

// src/app/comp-a/[email protected] '[email protected]/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); }}

Valószínűleg custom-theme.scssa komponensek összes témáját szeretné importálni:

// src/app/[email protected] '[email protected]/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);}

Majd importálja a fenti custom-theme.scssa theme.scss:

// [email protected] './custom-theme';@include custom-themes($my-theme);

Ez a hierarchia működik, és valószínűleg csak így lehet több témát támogatni .

Azonban legtöbbször csak egy témát támogatunk, és a mixin használata nehézkes lehet. Ennek a megközelítésnek főleg három hátránya van:

  1. Minden egyes színreferenciához külön .theme.scssfájlra van szükség.
  2. custom-theme.scsspontosan tudnia kell, hogy mely komponensek nyújtanak egyedi témákat. Ez felesleges függőségeket okoz.
  3. Ami a legfontosabb, hogy az összetevő szintű témájú fájlok nincsenek beágyazva.

Az első és a második pont eléggé magától értetődő. Hadd magyarázzak el egy kicsit a 3. pontról. Ez magában foglal néhány, a „View Encapsulation” elnevezésű háttérismeretet.

Az Angular a „View Encapsulation” nevű technikát használja a CSS komponens helyi szinten tartására. Más szavakkal, az egyik komponensre meghatározott szabályok ebben az összetevőben maradnak, és nem befolyásolják a többi komponenst.

Így szabadon definiálhatja a CSS osztály nevét az összetevőben anélkül, hogy aggódnia kellene a névütközések miatt. A nézetek beágyazása azonban csak akkor történik, ha a CSS keresztül van definiálva @Component, azaz @Component({ styleUrls: ['./comp-a.scss'] }).

Ami az egyedi témájú fájlunkat illeti comp-a.theme.scss, mivel közvetlenül az importálja custom-theme.scss, a szabályai nincsenek beágyazva, így az oldal összes elemére vonatkozni fog. A fenti példában a következő kódot használtam (ami ROSSZ volt!):

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

De ez az összes gombra alkalmazza a stílust, a comp-acsak azokhoz tartozó gombok helyett . Valami hasonlót kell tennie comp-a buttonahhoz, hogy ez helyesen működjön.

A közvetlen megközelítés

Ezért jobb megközelítést javasolok. A mixin használata helyett hagyjuk, hogy az egyes komponensek tartalmazzák a témafájlt, és közvetlenül használjuk a színdefiníciót.

Ebben a megközelítésben az összetevő témájú fájl a következőképpen fog kinézni:

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

És ennyi.

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.

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?

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.

$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.