Глибоке отримання / встановлення на Картах - CSS-хитрощі

Anonim

Працюючи над складними архітектурами Sass, нерідко використовується карта Sass для підтримки конфігурації та опцій. Час від часу на картах (можливо, на декількох рівнях) ви бачите такі карти, як ця з 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 );

Проблема таких карт полягає в тому, що отримати та встановити значення з вкладеного дерева непросто. Це, безумовно, щось, що ви хочете приховати в межах функцій, щоб уникнути необхідності робити це кожен раз вручну.

Глибоко отримати

Насправді, побудувати функцію для отримання глибоко вкладених значень з карти дуже просто.

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

Наприклад, якщо ми хочемо отримати значення, пов'язане з Mмакетом, з нашої конфігураційної карти, це так просто, як:

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

Зверніть увагу, що лапки навколо рядків необов’язкові. Ми додаємо їх лише для забезпечення читабельності.

Глибокий набір

З іншого боку, побудова функції для встановлення глибоко вкладеного ключа може бути дуже нудною.

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

Тепер, якщо ми хочемо оновити значення, пов'язане з Mмакетом, з нашої конфігураційної карти, ми можемо зробити:

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

Додаткові ресурси

Вищевказана функція не є єдиним рішенням цієї проблеми.

Бібліотека Sassy-Maps також надає map-deep-setта map-deep-getфункціонує. У тому ж напрямку, Уго Жиродель також написав extendфункцію стилю jQuery, щоб зробити вбудовану map-mergeрекурсивну та здатною об'єднати більше 2 карт одночасно.