Перейти к содержанию

Условные конструкции (защита примесей)

Условная конструкция — это самая часто используемая почти во всех языках программирования инструкция, к сожалению, отсутствующая в явном виде в 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.