#svelte
#стройный
Вопрос:
Я хочу отобразить массив объектов, используя each
блок. Мне нужно иметь возможность удалять элементы из массива с помощью обратных вызовов изнутри each
блока. Кроме того, для более сложных взаимодействий с пользовательским интерфейсом мне нужна ссылка на каждый компонент each
-block, который будет доступен в основном приложении.
Вот мой подход:
<script>
let items = [{text: "one"}, {text: "two"}];
function deleteItem(i) {
items.splice(i, 1);
items = items;
}
</script>
{#each items as item, i}
<button bind:this={items[i].ref} on:click={() => deleteItem(i)} >
{item.text}
</button>
<p />
{/each}
Понятно, что это приводит к ошибкам, таким как item[i] is undefined
, потому что при items
обработке сращивания bind:this
больше не может быть очищено должным образом.
Я попытался решить эту проблему, переместив ссылки на компоненты в отдельный массив. Но независимо от того, что я пытаюсь, я не могу синхронизировать ссылочный массив и массив объектов: всякий deleteItem()
раз, когда обрабатывается, я получаю null
значения внутри refs
массива. Вот один из моих подходов ( each
раздел, который печатает refs
массив, должен помочь отобразить null
значения):
<script>
import {tick } from "svelte";
let items = [{text: "one", id: 1}, {text: "two", id:2}];
let refs = [];
async function deleteItem(i) {
items.splice(i, 1);
await tick();
refs.splice(i, 1);
items = items;
console.log(refs);
}
</script>
{#each items as item, i (item.id)}
<button on:click={async () => deleteItem(i)} bind:this={refs[i]}>
{item.text}
</button>
<p />
{/each}
{#each refs as ref}
{ref}
<p />
{/each}
Я пробовал с и без tick()
, пробовал вставлять tick()
в разные места, с и без async
, с и без использования (item.id)
в каждом блоке. Как я могу синхронизировать ссылки и данные?
Ответ №1:
Способ обойти это refs
— очистить массив перед его использованием:
<script>
let items = [...]
let _refs = []
$: refs = _refs.filter(Boolean)
</script>
<button bind:this={_refs[i]}></button>
С помощью этого метода у вас все равно будут null
значения в исходном массиве _refs, но скопированная версия (ссылки) будет чистой.
Другой способ — привязать элемент к самому элементу, но это может быть нежелательно, если вы используете эти данные и в других местах:
<button bind:this={item.ref}>
(обратите внимание, что это все равно приведет к ошибкам, потому что связанный элемент исчезает во время среза, но обрабатывается только с присвоением, вы можете обойти это, выполнив нарезку и присвоение в одном, используя оператор filter)
items = items.filter((item, idx) => idx != i)
Комментарии:
1. Спасибо — ваш второй подход работает хорошо !