Я хочу создать компонент (в итоге он будет собран в web-component), который через prop будет принимать html строку.
Внутри svelte компонента из строки будет создан DOM элемент.
Этот DOM будет неким образом модифицирован, не суть, например, какой-то тег будет обернут в дополнительный или в ul добавлен новый li.
Главное - в момент модификации DOM я хочу добавить элементам атрибуты, которые должны будут распознаны svelte как функции и выражения, а не как строковые литералы.
Поясню.
Вот мы обрабатываем DOM (который создали из переданной html строки через prop):
<script>
import { onMount } from 'svelte';
export let htmlStringMenu;
let menuElement;
let isActive = false;
function createMenuElement() {
if (typeof htmlStringMenu === 'string') {
const tempElement = document.createElement('div');
tempElement.innerHTML = htmlStringMenu;
menuElement = tempElement?.firstChild?.nextElementSibling;
// Пример добавления атрибута.
const link = menuElement.querySelector('#menu-item');
link.setAttribute('on:click','{handleMenuItemClick}');
// Пример добавления выражения.
link.setAttribute('class','{isActive ? "active" : ""}');
}
}
onMount(() => {
createMenuElement();
});
function handleMenuItemClick(event) {
const menuItem = event.target;
console.log(menuItem);
}
</script>
<div>
<div>
{#if menuElement}
{@html menuElement.outerHTML}
{/if}
</div>
</div>
Функция "handleMenuItemClick" и добавление класса не будут работать, т.к. при отрисовке разметки на странице, Svelte не воспримет "handleMenuItemClick" как ссылку на функцию, а добавление класса как выражение, для него это будут просто строки.
Вопрос, как сделать так, чтобы Svelte подхватил это всё и понял, что "handleMenuItemClick" - это обработчик клика, а isActive - это реактивная переменная?
Проблемы нет, если все это описано в статичном шаблоне внутри svelte компонента, но проблема в том, что это не статичный шаблон, поэтому передается html-строка, она может и будет меняться.
Получается передаем html строку, а получаем интерактивное "приложение"
<custom-svelte-menu htmlStringMenu="menuInnerHTML" />