Как извлекать массив во время цикла с каждым в Svelte?

<script> 
   let myMessages = ["msg1", "msg2", "msg3"]
</script>

{#each myMessages as message}
    <div>{message}</div>
{/each}

Я хотел бы удалить каждый элемент из myMessages после того, как он был добавлен в DOM, чтобы в конце myMessages было пустым?
(вариант этого - добавить условие {#if} в цикл и удалить, только если элемент удовлетворяют этому условию)


person comte    schedule 15.05.2020    source источник
comment
Ваш шаблон отражает состояния вашего компонента / свойств. Если вы удалите элемент myMessages, DOM изменится. Так что то, о чем вы спрашиваете, - не лучшая идея.   -  person Jérémie B    schedule 18.05.2020
comment
@ JérémieB Разве реактивность не является целью адаптации DOM к изменениям состояния? Когда я помещаю новые элементы в myMessages, они обновляются до DOM, это нормальное поведение, и это именно то, для чего разработан Svelte? Так что, если у вас есть реактивность с push, вы ожидаете такой же реактивности с pop. Хотя я могу кое-что пропустить.   -  person comte    schedule 19.05.2020
comment
Вы хотите обновить DOM, когда элемент удаляется из myMessages? Ваш вопрос касался обновления myMessages после рендеринга DOM   -  person Jérémie B    schedule 19.05.2020
comment
@ JérémieB, вы правы. Мой вопрос был больше в том, как узнать, когда DOM обновляется, чтобы я мог вытолкнуть визуализированный элемент из моей переменной. Думаю, я должен предположить, что это гарантировано.   -  person comte    schedule 26.05.2020


Ответы (3)


Система реактивности Svelte основана на операторе присваивания =
Мутации в массиве (с такими методами, как with pop()) не обнаружены.

myMessages.pop()
myMessages = myMessages // this line will trigger svelte to update the dom
person Bob Fanger    schedule 24.05.2020

В отсутствие отзывов о рендеринге DOM я бы согласился. Итак, чтобы отобразить msg1 и затем вставить его, я бы поступил следующим образом:

<script> 
  let myMessages = []
  let tmpMessages = myMessages
  # then add msg1 to myMessages, render it and pop it
  myMessages.push("msg1")
  tmpMessages = myMessages
  myMessages.pop()
</script>

{#each tmpMessages as message}
  <div>{message}</div>
{/each}
person comte    schedule 26.05.2020

Это может быть достигнуто путем создания компонента сообщения, который отправляет собственное удаление (удаление из массива) родительскому приложению при создании / монтировании. Таким образом, позже в массив myMessages можно было бы добавить еще больше сообщений с той же функциональностью.

Демо-репликация REPL - ›https://svelte.dev/repl/7738ecf69c224219b9f3b171ce8fd3fa?version=3.38.2

[App.svelte]

<script>
  import { onMount } from 'svelte';
  import Message from './Message.svelte'
    
  let myMessages = ["msg1", "msg2", "msg3"]

// add two additional Messages 1,5s after App creation  
onMount( () => {
    setTimeout(function() {
      myMessages = [...myMessages, "msg4","msg5"];
    }, 1500);
});
    
function deleteMessage(event){
    myMessages = myMessages.slice(1)
    console.log(myMessages)
}   
</script>

{#each myMessages as message}
    <Message {message} on:delete={deleteMessage}/>
{/each}
[Message.svelte]
<script>
    import { onMount } from 'svelte';
    import { createEventDispatcher } from 'svelte';
    const dispatch = createEventDispatcher();

    export let message;
    
onMount( () => {
    setTimeout(function() {
      dispatch('delete', {          
        });
    }, 3000);
}); 
</script>

<div> {message} </div>

Или, как вариант, поскольку информация не отправляется, а запускается только удаление, без такой отправки - ›Demo REPL -› https://svelte.dev/repl/692afed5f9274d9f8f6630c23cc22627?version=3.38.2

[App.svelte]
<script>
    import { onMount } from 'svelte';
  import Message from './Message.svelte'
    
    let myMessages = ["msg1", "msg2", "msg3"]
    
// add two additional Messages 1,5s after App creation 
onMount( () => {
    setTimeout(function() {
      myMessages = [...myMessages, "msg4","msg5"];
    }, 1500);
});
    
function deleteMessage() {
    // delete first element in arr
    myMessages = myMessages.slice(1)
    console.log(myMessages)
}   
    
</script>

{#each myMessages as message}
    <Message {message} {deleteMessage} />
{/each}
[Message.svelte]
<script>
    import { onMount } from 'svelte';
    
    export let message;
    export let deleteMessage;
    
onMount( () => {
    setTimeout(function() {
        deleteMessage();
    }, 3000);
}); 
</script>

<div> {message} </div>
person Corrl    schedule 02.06.2021