Deep Get / Set în Maps - CSS-Tricks

Anonim

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ă Maspectului 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ă Maspectului 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-getfuncții. Pe aceeași linie, Hugo Giraudel a scris, de asemenea, o extendfuncție în stil jQuery pentru a face map-mergerecursivul încorporat și să poată combina mai mult de 2 hărți simultan.