Når du arbejder på komplekse Sass-arkitekturer, er det ikke ualmindeligt at bruge Sass-kort til at opretholde konfiguration og muligheder. Fra tid til anden kan du se kort på kort (muligvis på flere niveauer) som denne fra 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 );
Problemet med sådanne kort er, at det ikke er let at hente og indstille værdier fra det indlejrede træ. Dette er bestemt noget, du vil skjule inden for funktioner for at undgå at skulle gøre det manuelt hver gang.
Dybt få
Faktisk er det meget let at opbygge en funktion til at hente dybt indlejrede værdier fra et kort.
/// 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; )
For eksempel, hvis vi vil hente den værdi, der er knyttet til M
layoutet fra vores konfigurationskort, er det så let som:
$m-breakpoint: map-deep-get($o-grid-default-config, "layouts", "M"); // 610px
Bemærk, at citater omkring strenge er valgfri. Vi tilføjer dem kun af hensyn til læsbarhed.
Dybt sæt
På den anden side kan det være meget kedeligt at opbygge en funktion til at indstille en dybt indlejret nøgle.
/// 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; )
Hvis vi nu vil opdatere den værdi, der er knyttet til M
layoutet fra vores konfigurationskort, kan vi gøre:
$o-grid-default-config: map-deep-set($o-grid-default-config, "layouts" "M", 650px);
Ekstra ressourcer
Ovenstående funktion er ikke den eneste løsning på dette problem.
Sassy-Maps-biblioteket tilbyder map-deep-set
og map-deep-get
fungerer også. På samme måde har Hugo Giraudel også skrevet en jQuery-stil- extend
funktion for at gøre den indbyggede map-merge
rekursive og i stand til at flette mere end 2 kort på én gang.