Deep Get / Set i Maps - CSS-tricks

Anonim

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 Mlayoutet 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 Mlayoutet 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-setog map-deep-getfungerer også. På samme måde har Hugo Giraudel også skrevet en jQuery-stil- extendfunktion for at gøre den indbyggede map-mergerekursive og i stand til at flette mere end 2 kort på én gang.