Стройный: использование «привязки: это» внутри «каждого» блока

#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. Спасибо — ваш второй подход работает хорошо !