внедрение сгенерированных Svelte узлов в статическую DOM

У меня есть статический HTML-файл, и я хочу дополнить его динамическими компонентами Svelte:

<ul id="list">
    <li>first</li>
    <!-- dynamic list items should be added in between static ones -->
    <li>last</li>
</ul>

(Это упрощенный пример; «первый» и «последний» элементы более сложные, повторная генерация их в Svelte невозможна.)

import List from "./List.svelte";

new List({
    target: document.querySelector("#list"),
    props: {
        items: ["foo", "bar"]
    }
});
<script>
let items;
</script>

{#each items as item}
<li>{item}</li>
{/each}

Тем не менее, это добавляет динамические элементы в конец списка. Есть ли идиоматический декларативный способ вставить их в середину вместо этого?

Единственное решение, которое я могу придумать, - это громоздкие недекларативные манипуляции с DOM:

<script>
import { onMount } from "svelte";

let items;

onMount(() => {
    let container = ref.parentNode;
    container.removeChild(ref);
    // manually change order
    let last = container.querySelectorAll("li")[1];
    container.appendChild(last);
})
</script>

<span bind:this={ref} hidden />

{#each items as item}
<li>{item}</li>
{/each}

(Я даже не уверен, что это действительно так, потому что span элементы не разрешены как прямые ul потомки, плюс ручной сброс ref может запутать Svelte?)


person AnC    schedule 20.10.2019    source источник
comment
Я не знаю, зачем вы это делаете. Но вернемся к вашему вопросу. Точно так же, как вы передаете середину вашему компоненту, вы можете передать первый и последний элементы в компонент.   -  person voscausa    schedule 20.10.2019
comment
Я не уверен, что вы имеете в виду. Передача этих ранее существовавших узлов DOM компоненту не работает: items: ["foo", ...document.querySelectorAll("#list li"), "bar"] приводит к отображению [object HTMLLIElement], что разочаровывает. (Я делаю это, потому что верю в прогрессивное улучшение, используя Svelte для расширения существующей архитектуры, а не подчиняя ее с помощью Svelte, захватившего контроль над всей страницей.)   -  person AnC    schedule 22.10.2019


Ответы (1)


Вы можете использовать опцию anchor для монтирования компонента рядом с определенным узлом:

import List from "./List.svelte";

const target = document.querySelector("#list");
const anchor = target.lastChild; // node to insert component before

new List({
    target,
    anchor,
    props: {
        items: ["foo", "bar"]
    }
});

Демонстрация: https://svelte.dev/repl/1a70ce8abf2341ee8ea817228e5 / а>

Полный API задокументирован здесь: https://svelte.dev/docs#Client-side_component_API

person Rich Harris    schedule 10.11.2019
comment
О, спасибо (также за Svelte в целом) - не знаю, как я это пропустил. - person AnC; 11.11.2019