Când lucrați la arhitecturi complexe Sass, nu este neobișnuit să utilizați hărți Sass pentru a menține configurația și opțiunile. Din când în când, veți vedea hărți în hărți (posibil pe mai multe niveluri), cum ar fi acesta din o-grid:
$o-grid-default-config: ( columns: 12, gutter: 10px, min-width: 240px, max-width: 1330px, layouts: ( S: 370px, // ≥20px columns M: 610px, // ≥40px columns L: 850px, // ≥60px columns XL: 1090px // ≥80px columns ), fluid: true, debug: false, fixed-layout: M, enhanced-experience: true );
Problema cu astfel de hărți este că nu este ușor să obțineți și să setați valori din arborele imbricat. Acesta este cu siguranță ceva ce doriți să ascundeți în cadrul funcțiilor pentru a evita să faceți acest lucru manual de fiecare dată.
Adânc
De fapt, construirea unei funcții pentru a obține valori adânc imbricate dintr-o hartă este foarte ușoară.
/// Map deep get /// @author Hugo Giraudel /// @access public /// @param (Map) $map - Map /// @param (Arglist) $keys - Key chain /// @return (*) - Desired value @function map-deep-get($map, $keys… ) ( @each $key in $keys ( $map: map-get($map, $key); ) @return $map; )
De exemplu, dacă dorim să obținem valoarea asociată M
aspectului din harta noastră de configurare, este la fel de ușor ca:
$m-breakpoint: map-deep-get($o-grid-default-config, "layouts", "M"); // 610px
Rețineți că ghilimelele din jurul șirurilor sunt opționale. Le adăugăm doar din motive de lizibilitate.
Set profund
Pe de altă parte, construirea unei funcții pentru a seta o cheie profund imbricată poate fi foarte obositoare.
/// Deep set function to set a value in nested maps /// @author Hugo Giraudel /// @access public /// @param (Map) $map - Map /// @param (List) $keys - Key chaine /// @param (*) $value - Value to assign /// @return (Map) @function map-deep-set($map, $keys, $value) ( $maps: ($map,); $result: null; // If the last key is a map already // Warn the user we will be overriding it with $value @if type-of(nth($keys, -1)) == "map" ( @warn "The last key you specified is a map; it will be overrided with `#($value)`."; ) // If $keys is a single key // Just merge and return @if length($keys) == 1 ( @return map-merge($map, ($keys: $value)); ) // Loop from the first to the second to last key from $keys // Store the associated map to this key in the $maps list // If the key doesn't exist, throw an error @for $i from 1 through length($keys) - 1 ( $current-key: nth($keys, $i); $current-map: nth($maps, -1); $current-get: map-get($current-map, $current-key); @if $current-get == null ( @error "Key `#($key)` doesn't exist at current level in map."; ) $maps: append($maps, $current-get); ) // Loop from the last map to the first one // Merge it with the previous one @for $i from length($maps) through 1 ( $current-map: nth($maps, $i); $current-key: nth($keys, $i); $current-val: if($i == length($maps), $value, $result); $result: map-merge($current-map, ($current-key: $current-val)); ) // Return result @return $result; )
Acum, dacă dorim să actualizăm valoarea asociată M
aspectului din harta noastră de configurare, putem face:
$o-grid-default-config: map-deep-set($o-grid-default-config, "layouts" "M", 650px);
Resurse suplimentare
Funcția de mai sus nu este singura soluție la această problemă.
Biblioteca Sassy-Maps oferă map-deep-set
și map-deep-get
funcții. Pe aceeași linie, Hugo Giraudel a scris, de asemenea, o extend
funcție în stil jQuery pentru a face map-merge
recursivul încorporat și să poată combina mai mult de 2 hărți simultan.