Deep Get / Set in Karten - CSS-Tricks

Anonim

Bei der Arbeit an komplexen Sass-Architekturen ist es nicht ungewöhnlich, Sass-Maps zu verwenden, um Konfiguration und Optionen beizubehalten. Von Zeit zu Zeit sehen Sie Karten in Karten (möglicherweise auf mehreren Ebenen) wie diese von 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 );

Das Problem bei solchen Karten ist, dass es nicht einfach ist, Werte aus dem verschachtelten Baum abzurufen und festzulegen. Dies ist definitiv etwas, das Sie in Funktionen verbergen möchten, um zu vermeiden, dass Sie dies jedes Mal manuell tun müssen.

Tief bekommen

Tatsächlich ist es sehr einfach, eine Funktion zum Abrufen tief verschachtelter Werte von einer Karte zu erstellen.

/// 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; )

Wenn wir beispielsweise den dem MLayout zugeordneten Wert aus unserer Konfigurationszuordnung abrufen möchten , ist dies so einfach wie:

$m-breakpoint: map-deep-get($o-grid-default-config, "layouts", "M"); // 610px

Beachten Sie, dass Anführungszeichen um Zeichenfolgen optional sind. Wir fügen sie nur aus Gründen der Lesbarkeit hinzu.

Tief gesetzt

Andererseits kann das Erstellen einer Funktion zum Festlegen eines tief verschachtelten Schlüssels sehr mühsam sein.

/// 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; )

Wenn wir nun den dem MLayout zugeordneten Wert aus unserer Konfigurationszuordnung aktualisieren möchten , können wir Folgendes tun:

$o-grid-default-config: map-deep-set($o-grid-default-config, "layouts" "M", 650px);

Zusätzliche Ressourcen

Die obige Funktion ist nicht die einzige Lösung für dieses Problem.

Die Sassy-Maps-Bibliothek bietet auch map-deep-setund map-deep-getFunktionen. In diesem Sinne hat Hugo Giraudel auch eine extendFunktion im jQuery-Stil geschrieben , um die integrierte Funktion map-mergerekursiv zu machen und mehr als zwei Karten gleichzeitig zusammenzuführen.