Условные конструкции (защита примесей)
Условная конструкция — это самая часто используемая почти во всех языках программирования инструкция, к сожалению, отсутствующая в явном виде в Less.
Обычно, различают три вида условных конструкций по количеству ветвей: одно-, дву- и многоветвевую.
В JavaScript очень часто встречаются двуветвевые условные конструкции, где в зависимости от результата выражения выполняется тот или иной блок (true или false):
if (выражение) {
// True
} else {
// False
}
Ситуация в Less
В Less нет такого понятия, как условная конструкция. Здесь оперируют понятием — защита примесей. Ниже представлен обычный if
:
.mixin(@a, @b) when (выражение) {
// True
}
Примесь будет выполняться только тогда, когда выражение, указанное после ключевого слова when
будет истинно.
Операторы отношений
Операторы отношений: «меньше» (<
), «больше» (>
), «меньше или равно» (=<
или <=
),«больше или равно» (>=
) и «равно» (=
) сравнивают значения так же, как и в JavaScript. Каждый из них возвращает логическое значение.
Замечание
Оператор отношения «меньше или равно» (
=<
или<=
) отличается от аналогичного в JavaScript, где его запись имеет только один вид (<=
). В соответствии с документацией принято использовать (=<
).
Логическое НЕ, И и ИЛИ
Условия могут содержать ключевое слово not
, являющееся аналогом привычного нам по JavaScript отрицания !
.
Например, следующая примесь будет выполняться, если переданное ей значение @value
не равно нулю.
.mixin(@value) when not (@value = 0) {
color: #777;
}
Также, условия можно объединять, создавая более конкретные условия. Для этого используется ключевое слово and
.
.mixin(@value) when (@value > 0) and (@value =< 100) {
color: #777;
}
Ключевое слово and
можно опускать, используя взамен запятую:
.mixin(@value) when (@value > 0), (@value =< 100) {
color: #777;
}
Начиная с версии 2.6.0 компилятор поддерживает ключевое слово or
, соответствующее логическому «ИЛИ». Синтаксис повторяет синтаксис ключевого слова and
, но никаких синонимов взамен не предлагает (у and
синонимом является запятая):
.mixin(@value) when (@value > 0) or (@value = -1) {
content: @value;
}
Замечание
Логический оператор
and
имеет больший приоритет, чем логический операторor
, как и в любом языке программирования.
Помимо написанных вручную условий, можно использовать некоторые встроенные функции для проверки величин на совпадение с различными типами и размерностями.
Работа с типами данных
В главе 4 были рассмотрены функции для определения типа данных, которыми оперирует пользователь препроцессора Less. Все эти функции можно использовать в условном операторе. Причём важно отметить, что Less автоматически преобразует результат выражения в логическое значение, как это делает JavaScript, вызывая для него функцию Boolean()
.
Так, например, рассмотренная ранее функция isnumber()
, проверяющая являются ли предоставленные ей данные числом, может применяться следующим образом:
.return-number(@number) when (isnumber(@number)) {
content: @number;
}
.true {
.return-number(123);
}
.false {
.return-number("123");
}
В первом случае будет создан селектор .true
, так как значение, передаваемое в примесь, является числом. Во втором же случае, передаваемое значение — строка, что означает false
.
Конструкция if {} else {}
С помощью ключевого слова default()
можно определить примесь по умолчанию, которая будет выполняться при условии, что другие примеси не сработали.
.mixin(@a, @b) when (@a > @b) {
content: if;
}
.mixin(@a, @b) when (default()) {
content: else;
}
Вызовем примесь mixin
с параметрами (3, 1). В этом случае выполняется первая примесь, потому что введённые данные подходят под указанное в ней выражение (3 больше чем 1).
Если вызвать эту же примесь с параметрами (1, 1), то выполнится вторая примесь, так как выражение первой примеси вернуло false
.
Конструкция if {} else if {} else {}
Ситуация полностью аналогична предыдущей, с той лишь разницей, что примесей будет три:
.mixin(@a, @b) when (@a > @b) {
content: if;
}
.mixin(@a, @b) when (@a < @b) {
content: else if;
}
.mixin(@a, @b) when (default()) {
content: else;
}
Теперь условная конструкция выводит if
, если a больше b, else if
, если a меньше b, иначе else
.
Пример 5.1.1
Разберём работу примеси, которая генерирует внутренние отступы блока по правилу:
- Если указан один параметр, то генерировать свойство с одним значением.
- Если указано два параметра, то генерировать свойство с двумя значениями.
- и т.д.
Итак, необходимо использовать значения по умолчанию для того, чтобы не приходилось каждый раз указывать значения для всех параметров:
.padding(@t: none, @r: none, @b: none, @l: none) {
}
Теперь можно приступить к написанию условий:
.padding(@t: none, @r: none, @b: none, @l: none) {
& when not (@t = none) { padding+_: @t; }
& when not (@r = none) { padding+_: @r; }
& when not (@b = none) { padding+_: @b; }
& when not (@l = none) { padding+_: @l; }
}
Здесь использовалась возможность слияния значения свойств, которая обсуждалось в главе 4.
В итоге мы имеем примесь, которая выводит:
.padding(1px) // padding: 1px;
.padding(1px, 2px) // padding: 1px 2px;
...
Примеси как функции и условные конструкции
Следует аккуратно использовать сокращённую запись условной конструкции, которая имеет вид:
.mixin(@a) {
& when (@a = 1) {
@return: value;
}
}
Если вызвать эту примесь сейчас с параметром 1 и попытаться получить значение переменной @return
, то компилятор выдаст ошибку, говорящую о том, что такой переменной нет:
.test {
.mixin(1);
content: @return;
}
Ошибка имеет вид:
NameError: variable @return is undefined in
C:\...\a.test on line 9, column 12:
8 .mixin(1);
9 content: @return;
10 }
Кстати, вы заметили, что я создал файл с расширением .test
, и компилятор корректно его обработал? Напомню, что это обсуждалось в главе 1 (Импорт стилей в Less).
Связано это с тем, что ссылка на родительский селектор (&) создаёт новую область видимости. Подробнее об этом в главе 3 в разделе «Области видимости».
В тоже время, если использовать полную запись, то ошибки не будет:
.mixin(@a) when (@a = 1) {
@return: value;
}
.test {
.mixin(1);
content: @return;
}
Этот код будет генерировать селектор .test
со свойством content
, имеющим значение переменной @return
.