Deep Get / Set en mapas - Trucos CSS

Tabla de contenido

Cuando se trabaja en arquitecturas Sass complejas, no es raro utilizar mapas Sass para mantener la configuración y las opciones. De vez en cuando, verá mapas dentro de mapas (posiblemente en varios niveles) como este de 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 );

El problema con estos mapas es que no es fácil obtener y establecer valores del árbol anidado. Definitivamente, esto es algo que desea ocultar dentro de las funciones para evitar tener que hacerlo manualmente cada vez.

Obtener profundo

En realidad, crear una función para obtener valores profundamente anidados de un mapa es muy fácil.

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

Por ejemplo, si queremos obtener el valor asociado al Mdiseño de nuestro mapa de configuración, es tan fácil como:

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

Tenga en cuenta que las comillas alrededor de las cadenas son opcionales. Solo los agregamos por motivos de legibilidad.

Conjunto profundo

Por otro lado, crear una función para establecer una clave profundamente anidada puede resultar muy tedioso.

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

Ahora bien, si queremos actualizar el valor asociado al Mdiseño desde nuestro mapa de configuración, podemos hacer:

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

Recursos extra

La función anterior no es la única solución a este problema.

La biblioteca Sassy-Maps también proporciona map-deep-sety map-deep-getfunciones. En la misma línea, Hugo Giraudel también ha escrito una extendfunción al estilo jQuery para hacer que el incorporado sea map-mergerecursivo y pueda fusionar más de 2 mapas a la vez.

Articulos interesantes...