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'); }
Последние мысли
Итак, у вас есть три решения:
- Назовите свои константы особым образом, чтобы отличать их от переменных.
- Используйте карту констант, чтобы сохранить их все, и создайте небольшую функцию, чтобы получить их.
- Создайте «геттеры» и «сеттеры», чтобы иметь простую, но мощную систему.
Насколько я понимаю, я бы, наверное, выбрал первый вариант. Snakerized переменные в верхнем регистре. Но что бы ни плавало на вашей лодке, верно? Не стесняйтесь играть с кодом на SassMeister.
Играйте с простой версией на SassMeister . Тогда иди и проверить полную версию , также на Sassmeister.