Использование слотов внутри {@html}

#svelte #svelte-3

#стройный #стройный-3

Вопрос:

В моем пользовательском компоненте у меня была строка html из сторонней библиотеки (у меня есть доступ на запись к исходному коду). Я хотел поместить <slot></slot> в тело этого фрагмента html.

Строка html из сторонней библиотеки может выглядеть следующим образом:

 <div>
    <!-- <slot></slot> is supposed to be here -->
</div>
 

MyComponent.стройный:

 <script>
    $: htmlString = lib.getHtmlFragment(/* optional body html*/);
</script>

{@html htmlString}

<!-- How do I put slots inside the htmlString -->
 

Приложение.стройный:

 <MyComponent>
   <input bind:value />
</MyComponent>
 

Итак, как я могу поместить <slot></slot> завернутый внутри {@html htmlString} , не теряя реактивности слота?

Ответ №1:

Это невозможно, как описано, но это было бы довольно круто. Мы можем подтвердить, что это сбой с фиктивными данными, подобными этому REPL.

Вы можете заменить div определенным идентификатором, который находится в динамическом содержимом, на onMount содержимое с прорезями, но вы потеряете реактивность, как показано в этом REPL, поскольку он уже скомпилирован после прохождения блока @html.

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

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

С помощью последних двух решений убедитесь, что вокруг предоставленного динамического содержимого нет тега родительского div. Svelte всегда будет заставлять один @html тег сам по себе быть допустимым HTML и закрывать открытые теги при разделении HTML-строки подобным образом, что сделает вашу разметку непредсказуемой для целей CSS / сканирования / тестирования.

Комментарии:

1. Спасибо за подробный ответ. Я смотрю на них.

Ответ №2:

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

 <script>
  import { onMount } from 'svelte';
  import MySlotComponent from './MySlotComponent.svelte';

  export let html; // external html
  let el;

  onMount(() => {
    let target = el.querySelector(...);
    const cpn = new MySlotComponent({ target });

    return () => cpn.$destroy();
  });
</script>

<div bind:this={el}>
  {@html html}
</div>