🚀 Быстрый совет по Svelte: стилизация слотов с условными именами

Эта статья изначально была опубликована на моей странице Dev.to

👋 Привет, мир!

В моем предыдущем посте я описал, как вы можете выборочно стилизовать дочерние элементы <slot>. Теперь мы собираемся немного уменьшить масштаб и посмотреть, как мы можем стилизовать сами контейнеры <slot>.

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

Насколько мне известно, есть 3 основных способа сделать это:

  1. Стиль обернутого компонента
  2. Стиль, основанный на имени [slot="..."]
  3. Используйте условные слоты

Теперь давайте рассмотрим каждый из них на примере компонента <Modal> с дополнительным слотом actions для действий формы:

Нетерпеливый? Суть в том, чтобы использовать условные слоты 🤓

1. Стиль обернутого компонента

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

<section>
  <div>
    <slot />
  </div>
  <footer>
    <slot name="actions" />
  </footer>
</section>
<style lang="postcss">
  section {
    background: white;
    border-radius: 1rem;
    box-shadow: 0 0.4rem 0.5rem rgba(0, 0, 0, 0.15);
  }
  div {
    padding: 2rem;
  }
  div :global(> :first-child) {
    margin-top: 0;
  }
  div :global(> :last-child) {
    margin-bottom: 0;
  }
  footer {
    background: #ececec;
    border-bottom-left-radius: 1rem;
    border-bottom-right-radius: 1rem;
    padding: 1.25rem 2rem;
  }
</style>

Затем мы можем использовать этот компонент следующим образом:

<h1>With slot content</h1>
<Modal>
  <p>Hello, World!</p>
  <div slot="actions">
    <button>Click me</button>
  </div>
</Modal>
<h1>Without slot content</h1>
<Modal>
  <p>Hello, World!</p>
</Modal>

Проблемная часть этого решения заключается в том, что если в слоте нет контента, он все равно будет отображаться, что, конечно, не то, что нам действительно нужно:

Это происходит из-за того, что тег <footer> существует в DOM и, таким образом, к нему применен стиль, поэтому мы видим серое поле, а не ничего, как мы ожидали.

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

Посмотрите это в Svelte REPL здесь.

2. Стиль на основе имени [slot="..."]

Единственная разница здесь в том, что мы собираемся стилизовать слот, используя только имя слота в качестве селектора. Для этого сначала удалите из слота оберточный тег <footer>:

<section>
  <div>
    <slot></slot>
  </div>
- <footer>
-    <slot name="actions"></slot>
-  </footer>
+  <slot name="actions"></slot>
</section>

Далее мы будем использовать синтаксис [slot="..."] в сочетании с модификатором :global для выбора слота по его имени. Таким образом, мы можем стилизовать слот без добавления дополнительной разметки:

-footer {
+section :global([slot="actions"]) {
  /* ...styling remains the same... */
}

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

На самом деле, поскольку в слот не передается контент, он даже не отображается в DOM:

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

Посмотрите это в Svelte REPL здесь.

3. Используйте условные слоты

Это, вероятно, «правильный» способ решения этой проблемы в большинстве случаев, поскольку он не требует каких-либо странных волшебств CSS, как в предыдущем примере.

Мы просто заключаем слот в условное выражение, что заставит его отображать слот и его содержимое только в том случае, если слоту было предоставлено содержимое в потребляющем компоненте:

{#if $$slots.actions}
  <footer>
    <slot name="actions"></slot>
  </footer>
{/if}

Свойство $$slots — это свойство, которое Svelte предоставляет всем компонентам и которое представляет собой словарь именованных слотов (узнайте больше о $$slots здесь).

Причина, по которой я считаю это «правильным» способом решения этой проблемы, заключается в том, что никакая разметка не отображается в браузере, и вам не нужно делать какие-то хакерские :global модификации, как в примере № 2.

Кроме того, вы можете добавить переходы/анимацию, когда он смонтирован, как и другие элементы Svelte, что довольно удобно 😻

Посмотрите это в Svelte REPL здесь.

🎬 Плавник

Ну это все народ! 🐰

Надеюсь, это даст вам немного больше ясности при работе со стилем именованных слотов в Svelte!

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

Есть другие советы, идеи, отзывы или исправления? Дайте мне знать в комментариях! 🙋‍♂️

Не забудьте подписаться на меня на Dev.to (danawoodman), Twitter (@danawoodman) и/или Github (danawoodman)!

Фото автора Joshua Aragon на Unsplash