Как я могу вернуть обработанный HTML-код компонента Svelte?

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

  1. Создайте всплывающую подсказку с HTML или компонентом в качестве содержимого
  2. Без необходимости оборачивать компонент <Tooltip><element></Tooltip>
  3. Подключайтесь к готовым библиотекам для большей гибкости

Пожалуйста, посмотрите мой пример кода ниже. Он не работает в REPL из-за зависимостей Tippy.js, но у меня он работает с простым HTML в моем приложении. Вот почему я считаю, что я должен попытаться отрендерить компонент, который распознает свойства, как и любой другой, а затем каким-то образом взять его HTML и использовать его: вызов действия. (см. «content: 'Привет, я работаю!'») Он должен быть таким же простым в использовании, как во времена всплывающих подсказок jQuery.

Ссылка REPL: https://svelte.dev/repl/e8fdf98eb42445e3b791d7c908581a71?version=3.17.3


person Vael Victus    schedule 24.01.2020    source источник


Ответы (1)


Чтобы действительно «вернуть обработанный HTML», вам нужно будет скомпилировать с помощью generate: 'ssr' option и использовать Cmp.render() функция. Но вы не можете использовать такой компонент в DOM ...

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

<script>
const logHtml = el => {
  console.log(el.innerHTML)
}
</script>

<div use:logHtml> ... </div>

Или просто bind:this на элементах:

<script>
  let el
  $: if (el) console.log(el.innerHTML)
</script>

<div bind:this={el}> ... </div>

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

Вот пример действия, отображающего пользовательский компонент с tippy.js (см. обновленный REPL):

export function tipz(elem, { content, props, ...opts }) {
  let cmp

  const tp = tippy(elem, {
    onCreate() {
      cmp = new content({
        target: instance.popper.querySelector(".tippy-content"),
        props,
      });
    },
    ...opts
  })

  return {
    update(params) {
      // ensure reactivity
      if (cmp) {
        cmp.$set(params.props)
      }
    },
    destroy() {
      tp.destroy();
      if (cmp) {
        // cleanup component
        cmp.$destroy();
      }
    }
  };
}
person rixo    schedule 24.01.2020
comment
Большое спасибо! Я многому научился только из твоего ответа. Сейчас он работает, но возникли две проблемы: 1. Я получал странную __update ошибку. Оказалось, что в Svelte 3.16.7 была ошибка use: action, исправленная в 3.17.0! 2. Мне пришлось изменить onCreate, чтобы дополнительно передать , props, потому что он не создавался с их помощью. Обновленный REPL: svelte.dev/repl/ffd2b212ae9e48e4b1c0279e72b2b212ae9e48e4b1c02e3e3e3e4b07e2e3 - person Vael Victus; 24.01.2020
comment
О, вы правы, пропсы нужно передавать и при создании компонентов. Я исправил пример кода. Спасибо. - person rixo; 24.01.2020
comment
Я заметил, что это создает экземпляр компонента при инициализации, что означает, что если у меня на странице 50 элементов, получается 50 компонентов. Есть идеи, можно ли использовать new MyComponent без этого? - person Vael Victus; 25.01.2020
comment
Да, это возможно. В основном это зависит от вашей библиотеки, предоставляющей правильные хуки. Например, с помощью tippyjs вы можете создать хук new Cmp на onShow и $destroy на onHidden. new Cmp будет отображаться в DOM синхронно, поэтому вам не нужно беспокоиться о мерцании содержимого, потому что компонент отображается слишком поздно. Единственное, о чем стоит беспокоиться, если вы создаете компонент только тогда, когда отображается всплывающая подсказка, это то, что вам, вероятно, придется хранить новые реквизиты, поступающие через update, в локальную переменную или что-то в этом роде, чтобы быть уверенным, что компонент создается с помощью последние значения. - person rixo; 25.01.2020