Статьи

Работа с константами в Sass

Sass, как и JavaScript, не имеет встроенного способа реализации констант. Но прежде чем идти дальше, давайте кратко напомним о тех из вас, кто не очень осведомлен об этом жаргоне программирования.

В компьютерном программировании константа — это идентификатор, ассоциированное значение которого обычно не может быть изменено программой во время ее выполнения (хотя в некоторых случаях это можно обойти, например, с помощью самоизменяющегося кода). Многие языки программирования делают явное синтаксическое различие между постоянными и переменными символами.
Википедия

Таким образом, константа в основном является неизменной переменной. Однако, поскольку переменная является редактируемой по своей природе, нам нужно было новое имя, чтобы описать переменную, которая не… вы знаете, переменная. Следовательно, постоянная .

Итак, как я уже говорил, у Sass нет способа определить константы. И если вы спросите меня, это, вероятно, к лучшему. В декларативном, связанном со стилем языке, таком как CSS, потребность в неизменяемых значениях очень маловероятна. Но, как вы знаете, я парень, который делает сумасшедшие вещи, так что …

Пошли.

Как все это началось?

В компьютерном программировании существует соглашение, согласно которому авторы должны определять имена констант в виде заглавных строк в виде заглушек, например: LOOK_AT_ME_I_AM_A_CONSTANT .

Поэтому моей первой мыслью было положиться на соглашение об именах для определения констант в Sass. По сути, все переменные в верхнем регистре с заклейками должны рассматриваться как константы, поэтому никогда не должны быть отключены.

Например:

 $MAX_Z_INDEX: 2147483647; $PI: 3.1415926535897932384626433832795028841971693993751; $E: 2.71828182845904523536028747135266249775724709369995; 

Если вы спросите меня, вам, вероятно, стоит остановиться в большинстве случаев. Но если вам нравится добавлять некоторые дополнительные забавные / полезные вещи в ваш код, вы можете продолжить чтение.

Сохраняя это простым

Поэтому я подумал (и, очевидно, был не один ) о сборе всех констант в карте $CONSTANTS . Таким образом, даже для неопытного разработчика должно быть совершенно ясно, что эти значения не должны редактироваться.

 /// Constants map /// @type Map /// @prop {Number} MAX_Z_INDEX - 2147483647 /// @prop {Number} PI - 3.1415926535897932384626433832795028841971693993751 /// @prop {Number} E - 2.71828182845904523536028747135266249775724709369995 $CONSTANTS: ( 'MAX_Z_INDEX': 2147483647, 'PI': 3.1415926535897932384626433832795028841971693993751, 'E': 2.71828182845904523536028747135266249775724709369995 ); 

Хотя, так как не очень удобно использовать map-get() для извлечения значений из этой карты, давайте создадим небольшую функцию для их получения, которая называется const() .

 /// Constant getter /// @param {String} $name - Name of constant to get /// @return {*} Constant value /// @require $CONSTANTS /// @throw 'Unknown constant `#{$name}`.' @function const($name) { @if not map-has-key($CONSTANTS, $name) { @error 'Unknown constant `#{$name}`.'; } @return map-get($CONSTANTS, $name); } 

Эта функция вряд ли может быть проще: ей нужно только постоянное имя. Если его нет в карте $CONSTANTS , выдается ошибка. Не стесняйтесь избавиться от этого утверждения, если вы хотите вернуть null (что делает map-get , если ключ не существует) — это нормально. Насколько я понимаю, я чувствую, что если вы попытаетесь получить неизвестную константу, она потерпит неудачу.

Тогда вы бы использовали это так:

 .test { z-index: const('MAX_Z_INDEX'); } 

Это выглядит красиво, не правда ли? Мне нравится, как вы можете сразу увидеть из названия функции, что значение z-index является константой, а не каким-то магическим числом.

Толкая вещи дальше

Возможно, вы заметили, что наша текущая версия имеет дело только с чтением констант, а не с их созданием. Если вы хотите добавить новую константу, вы должны вручную записать ее на карту $CONSTANTS .

Так что, если бы у нас был способ динамически устанавливать константы? Это также позволило бы нам выдать ошибку, если мы попытаемся переопределить существующую константу. Это то, что мы собираемся сделать в этом последнем разделе.

Идея довольно проста, не волнуйтесь:

  • создать константный миксин, чтобы установить константу;
  • построить константную функцию, чтобы получить константу.

Мы сохраним идею карты $CONSTANTS , но инициализируем ее как пустую карту. Тогда константный миксин поместит в него новые константы.

 $CONSTANTS: () !global; 

Давайте начнем с нашего const mixin. Это должно быть довольно просто понять: если константа, которую мы пытаемся создать, уже существует, мы взрываемся. В этом весь смысл. Если нет, мы добавим его на карту.

 /// Constant setter /// @param {String} $name - Name of constant to get /// @param {*} $value - Constant value /// @return {*} - Constant value /// @require $CONSTANTS /// @throw 'Constant `#{$name}` already defined.' /// @output Nothing @mixin const($name, $value) { @if map-has-key($CONSTANTS, $name) { @error 'Constant `#{$name}` already defined.'; } $CONSTANTS: map-merge($CONSTANTS, ($name: $value)) !global; } 

Наша функция const должна быть примерно одинаковой длины:

 /// Constant getter /// @param {String} $name - Name of constant to get /// @return {*} - Constant value /// @require $CONSTANTS /// @throw 'Unknown constant `#{$name}`.' @function const($name) { @if not map-has-key($CONSTANTS, $name) { @error 'Unknown constant `#{$name}`.'; } @return map-get($CONSTANTS, $name); } 

Таким образом, у нас есть наш «получатель» и наш «установщик». Теперь мы готовы использовать нашу маленькую систему:

 // Initializing new constants @include const('MAX_Z_INDEX', 2147483647); @include const('PI', 3.1415926535897932384626433832795028841971693993751); @include const('E', 2.71828182845904523536028747135266249775724709369995); // Using a constant; // same API as before .test { z-index: const('MAX_Z_INDEX'); } 

Последние мысли

Итак, у вас есть три решения:

  1. Назовите свои константы особым образом, чтобы отличать их от переменных.
  2. Используйте карту констант, чтобы сохранить их все, и создайте небольшую функцию, чтобы получить их.
  3. Создайте «геттеры» и «сеттеры», чтобы иметь простую, но мощную систему.

Насколько я понимаю, я бы, наверное, выбрал первый вариант. Snakerized переменные в верхнем регистре. Но что бы ни плавало на вашей лодке, верно? Не стесняйтесь играть с кодом на SassMeister.

Играйте с простой версией на SassMeister . Тогда иди и проверить полную версию , также на Sassmeister.