Добавить директиву события в выражение svelte html? - PullRequest
0 голосов
/ 10 марта 2020

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

{@html 
`
 <button>
   click me
 </button>
`
}

Я хотел бы добавить обработчик событий директивы в html строка, а именно локально определенная функция, которая будет вызываться при нажатии кнопки. Что я пробовал до сих пор:

{@html 
`
 <button
   on:click="${()=>doSomething()}">
   click me
 </button>
`
}

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

1 Ответ

4 голосов
/ 10 марта 2020

Концептуально использование директивы @html равносильно выполнению el.innerHTML = myHtmlString.

Иначе говоря, в контексте вашей строки HTML вы полностью вне сферы Svelte (и полностью в нативная область браузера).

on:click - это специальный синтаксис Svelte, браузер не будет его обрабатывать. Поэтому, если вы хотите, чтобы в вашей строке HTML были события, вам нужно go вернуться к необработанному HTML / JS. То есть вместо этого используйте onclick.

Конечно, семантика onclick полностью отличается от семантики on:click. На onclick вы можете передать только строку, которая будет eval 'd, когда событие произойдет (тогда как с on:click вы передадите функцию reference , которая будет вызываться при событии случается).

Чтобы сделать это очень понятным, давайте вспомним синтаксис Svelte:

<button on:click={doSomething}>Click me</button>

Напротив, в raw HTML это будет выглядеть так:

{@html '<button onclick="doSomething()">Click click!</button>'}

Обратите внимание на важное различие: с onclick вам нужно вызвать функцию doSomething(), иначе ничего не произойдет при нажатии.

Теперь, дополнительное удовольствие: это doSomething функция должна быть доступна в области видимости ... То есть вы должны прикрепить ее к window:

<script context="module">
  // note: using context=module to avoid adding this function to window
  //       multiple times
  window.doSomething = () => { ... }
</script>
{@html '<button onclick="doSomething()">Click click!</button>'}

Это ужасно ... Вместо этого вы можете сделать что-то подобное, чтобы избежать загрязнения глобальная область действия:

<script>
  import { onMount } from 'svelte'

    const doSomething = () => { ... }

    onMount(() => {
        const btn = document.querySelector('#grab-me')
        btn.addEventListener('click', doSomething)
    })
</script>

{@html '<button id="grab-me">Click click!</button>'}

Теперь мы загрязняем идентификаторы DOM ... Мы могли бы избежать этого, добавив элемент управления Svelte, на который можно было бы ссылаться с помощью bind:this={el} ...

Подводя итог, лучше избегать динамических c элементов в @html строках, потому что вы теряете все Преимущества Svelte внутри них. @html лучше всего подходит для отображения содержимого c HTML.

Почему вы хотите поместить свою кнопку в строку вместо того, чтобы позволить Svelte управлять ею?

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

...