Я пишу стилизованные компоненты чуть больше года, и все это время я не понимал, что происходит с синтаксисом тегированных шаблонных литералов. Этот синтаксис также популярен для GraphQL, если вы его используете. Думаю, многие похожи на меня в том, что они впервые столкнулись со следующим синтаксисом: «Что ж, это выглядит забавно, но если мне удастся написать SCSS вместо этого громоздкого объекта javascript css, давайте попробуем».

Если бы ваш ответ был больше похож на мелодию: «Как это работает? Давай посмотрим! " Тогда я думаю, что вы на пути к величию, продолжайте в том же духе. Для остальных из нас иногда вам просто нужно двигаться дальше и использовать какую-то вещь на некоторое время, прежде чем у вас будет время и терпение, чтобы покопаться во внутренностях того, как это работает.

Что ж, вчера был день, когда мне надоело быть невежественным по этой теме, и это было намного проще, чем я думал.

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

Начнем с основ шаблонов с тегами

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

«Шаблон с тегами» - это функция, которая позволяет анализировать литералы шаблона. Вот быстрый пример его написания:

Наша функция довольно стандартна, она принимает массив строк для первого параметра и одну переменную для второго параметра. Магия случается, когда она вызывается. Вызов функции в таком формате:

taggedTemplate``

а не обычный:

taggedTemplate()

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

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

Синтаксис стилизованных компонентов

Теперь, когда мы рассмотрели основы шаблонов с тегами, давайте приступим к созданию нашей собственной styled функции. Мы начнем с базовой версии, которая имеет доступ к theme переменным.

Этот пример начинается с theme, объявленного вне области действия функции для облегчения доступа, который используется при вызове styled так же, как и в наших предыдущих примерах. Что отличает и стоит отметить, так это то, как мы расширяем variables в определении параметра функции.

function styled(css, ...variables) {
  // . . .
}

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

Другими словами, мы можем просто сделать это:

function styled(css, ...variables) {
  const computedCss = css
    .map((chunk, index) => `${chunk}${variables[index] || ''}`)
    .join('')
  return computedCss
}

Я называю каждую позицию в массиве css (массив строк) chunk. Мы записываем кусок, а затем объединяем его с переменной того же index. У нас может быть больше фрагментов, чем переменных, поэтому нам нужно будет проверить, существует ли переменная по этому индексу, и в противном случае ничего не вернуть (т.е. пустую строку).

Добавление обратных вызовов для доступа к теме и реквизитам

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

Мы поместили объект theme внутрь функции styled и добавили объект props с theme в качестве его свойства. Основное отличие функции состоит в том, что мы вызываем функцию в variables[index], когда значение существует в этой позиции. Это потому, что наша строка шаблона теперь передает функции обратного вызова, а не простые переменные.

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

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

Первоначально опубликовано на https://blog.jimmydc.com.