Статьи

Sass несколько аргументов, списков или Arglist

Я делаю много обзоров кода Sass. В том же духе я люблю читать код фреймворков. Излишне говорить, что я видел много вещей, как хороших, так и плохих, когда дело доходит до Sass.

Если есть что-то, что всегда заставляет меня скрипеть, когда я читаю Sass других людей, он видит миксины и функции, использующие списки вместо переменных-аргументов, или списки вместо нескольких именованных аргументов.

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

терминология

Прежде чем идти дальше, давайте кратко рассмотрим терминологию. И функции, и миксины могут принимать аргументы от 0 до бесконечности. Это означает, что вы можете сделать функцию без аргументов / миксин или функцию с множеством аргументов. Теперь давайте углубимся.

В Sass list Значение, для которого в качестве типа задан listtype-of ), представляет собой набор из нескольких значений определенного типа ( numberstringboolcolorlistmapnull Для более глубокого понимания списков Sass, я предлагаю вам прочитать мою статью об этом.

Наконец, что не менее важно, есть переменный аргумент . Возможно, вы не знали, что arglist Дело в том, что вы не можете легко создать arglist

Например:

 @mixin shadows($shadows...) {
  box-shadow: $shadows;
}

В этом примере $shadowsarglist Используя ... Он разделяет те же черты с обычным списком, за исключением того, что он всегда разделяется запятыми, поскольку несколько аргументов разделяются запятыми.

Теперь, когда мы в порядке с терминологией, пришло время определить, что и когда использовать. Давайте начнем с простого.

Переменный аргумент

Если вы не знаете, сколько аргументов будет передано в функцию / миксин, потому что их может быть ни одно, или столько же, сколько звезд во вселенной, это означает, что вы должны иметь дело с неизвестным числом аргументов, иначе arglist

Например, давайте рассмотрим линейно-градиентный миксин:

 @mixin linear-gradient($direction, $gradients...) {
  background-color: nth($gradients, 1);
  background-image: linear-gradient($direction, $gradients...);
}

.selector {
  @include linear-gradient(to right, magenta, red, orange, yellow, green, blue, purple);
}

Это идеальный случай для переменного аргумента, потому что в mixin может быть передано любое количество остановок цвета. Не используйте список только для зацикливания и создания списка через запятую … Это не имеет смысла.

Несколько аргументов

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

В большинстве случаев вы будете использовать несколько аргументов, а не listarglist Это общий случай использования, для работы функции / миксина нужны abc$a$b$c Если некоторые из этих аргументов имеют значение по умолчанию, вы добавляете это значение по умолчанию в сигнатуру миксина, например, $a$b$c: "default"

Одна вещь, о которой мало кто знает, это то, что установка нескольких аргументов в сигнатуре функции / миксина не обязательно означает, что вы должны передавать их по одному. Давайте отложим наш градиентный миксин и на минуту рассмотрим пустую функцию:

 @function dummy($a, $b, $c: "default") {
  // do stuff
}

Теперь предположим, что у вас есть список с именем $parameters

 $parameters: (true, 42, 'kittens');

Существует два способа вызова функции на основе вашего списка параметров. Либо как это, что не элегантно:

 $value: dummy(nth($parameters, 1), nth($parameters, 2), nth($parameters, 3));

Или вот так, инструктируя Sass передавать $parameters

 $value: dummy($parameters...);

Хотя вторая версия довольно удобна, она требует, чтобы $parameters Чтобы обойти это, существует третий способ сделать это, начиная с Sass 3.3, используя карту:

 $parameters: (
  'c': 'kittens',
  'a': true,
  'b': 42
);

$value: dummy($parameters...);

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

Вернуться к нашей первоначальной теме. Использование нескольких отдельных аргументов намного эффективнее, чем требование от пользователя передать список, потому что вы предоставляете им выбор: либо они могут передавать аргументы один за другим, либо все сразу с помощью списка или карты.

Так что подумайте дважды в следующий раз, когда вы захотите заменить пару аргументов списком на сигнатуру функции / миксина.

Список

Из того, что я могу сказать, довольно необычно иметь миксин или функцию, ожидающую список. Либо вы будете использовать несколько аргументов, потому что они все не связаны, либо вы передадите arglist

Список часто используется как внутренний инструмент для хранения нескольких значений в уникальной переменной. Тем не менее, некоторые функции / миксины могут ожидать список, потому что они фактически делают некоторые манипуляции с этим списком. Например, функция, проверяющая, содержится ли значение в списке, явно нуждается в списке для работы. Не названные аргументы, так как мы не знаем число. Не переменный аргумент, так как это единый объект.

 @function contains(/* List */ $haystack, /* Any */ $needle) {
  @return not not index($haystack, $needle);
}

Позвольте мне немного дрейфовать. Текущая версия Bourbon предоставляет миксин для определения размеров элементов . Идея проста: вы передаете ему одно значение, оно присваивает ему widthheightwidthheight

Теперь это легко выполнимо с чем-то вроде этого:

 /// Helper mixin to size elements
/// @param {Number} $width - Width
/// @param {Number} $height ($width) - Height
@mixin size($width, $height: $width) {
  width: $width;
  height: $height;
}

Если $height$width Это и элегантно и лаконично. Теперь я не совсем уверен, почему Бурбон решил пойти другим путем и попросить список.

 /// Helper mixin to size elements
/// @param {List} $size - Width and possibly height (but not mandatory)
@mixin size($size) {
  $height: nth($size, 1);
  $width: $height;

  @if length($size) > 1 {
    $height: nth($size, 2);
  }

  width: $width;
  height: $height;
}

Я имею в виду, почему? В этом случае нет никакого смысла использовать list Оба значения не связаны, поэтому они не должны быть упакованы в одну переменную. Кроме того, в Sass встроен способ установки значений по умолчанию непосредственно из подписи.

Единственное преимущество этой версии — не вводить запятую при вызове mixin:

 // Standard mixin
.selector {
  @include size(13px, 37px);
}

// Bourbon mixin
.selector {
  @include size(13px 37px);
}

Это, безусловно, не стоит, если вы спросите меня.

Tl; др

Если вы ожидаете неограниченное количество аргументов, не используйте listarglist Этот тип данных был разработан для такой цели.

Если вы ожидаете ограниченное количество аргументов, не используйте list Это позволит вам передавать их по одному или все сразу, используя список или карту.

Если вы ожидаете список для своего миксина / функции, используйте list Вы можете использовать arglist