Como remover um item de uma matriz em Vue.js

88

Eu sou novo no vue.js (2) e atualmente estou trabalhando em um aplicativo de evento simples. Consegui adicionar eventos, mas agora gostaria de excluí-los clicando em um botão.

HTML

    <div class="list-group">

        <div class="list-group-item" v-for="event in events">
            <h4 class="list-group-item-heading">
                {{ event.name }}
            </h4>

            <h5>
                {{ event.date }}
            </h5>

            <p class="list-group-item-text" v-if="event.description">{{ event.description }}</p>

            <button class="btn btn-xs btn-danger" @click="deleteEvent(event)">Delete</button>
        </div>

    </div>
</div>

JS (Vue)

new Vue ({
    el: '#app',

    data: {
        events: [
            {
                id: 1,
                name: 'Event 1',
                description: 'Just some lorem ipsum',
                date: '2015-09-10'
            },
            {
                id: 2,
                name: 'Event 2',
                description: 'Just another lorem ipsum',
                date: '2015-10-02'
            }
        ],

        event: { name: '', description: '', date: '' }
    },

    ready: function() {

    },

    methods: {

        deleteEvent: function(event) {
                this.events.splice(this.event);
        },

        // Adds an event to the existing events array
        addEvent: function() {
            if(this.event.name) {
                this.events.push(this.event);
                this.event = { name: '', description: '', date: '' };
            }
        }

    } // end of methods

});

Já tentei passar o evento para a função e depois deletar aquele com a função slice, pensei que era aquele código para deletar alguns dados do array. Qual é a melhor maneira mais limpa de excluir dados do array com um botão simples e um evento onclick?

Giesburts
fonte
Isso responde sua pergunta? Como remover um item específico da matriz?
ponury-kostek

Respostas:

147

Você está usando de splicemaneira errada.

As sobrecargas são:

array.splice (iniciar)

array.splice (start, deleteCount)

array.splice (start, deleteCount, itemForInsertAfterDeletion1, itemForInsertAfterDeletion2, ...)

Iniciar significa o índice que você deseja iniciar, não o elemento que deseja remover. E você deve passar o segundo parâmetrodeleteCount como 1, o que significa: "Quero deletar 1 elemento começando no índice {start}".

Então é melhor você ir com:

deleteEvent: function(event) {
  this.events.splice(this.events.indexOf(event), 1);
}

Além disso, você está usando um parâmetro, para acessá-lo diretamente, não com this.event.

Mas desta forma você parecerá desnecessário indexOfem cada deleção, para resolver isso você pode definir a indexvariável em seu v-for, e então passá-la ao invés do objeto de evento.

Isso é:

v-for="(event, index) in events"
...

<button ... @click="deleteEvent(index)"

E:

deleteEvent: function(index) {
  this.events.splice(index, 1);
}
Edmundo rodrigues
fonte
Incrível, já pensei que estava usando splice errado. Você pode me dizer qual é a diferença entre splice e slice? Obrigado!
Giesburts
1
Certo. Basicamente, o sPlice modifica o array original, enquanto o slice cria um novo array. Mais informações aqui: tothenew.com/blog/javascript-splice-vs-slice
Edmundo Rodrigues
Você também pode usar $ remove como um atalho.
Chris Dixon
2
@EdmundoRodrigues, obrigado por este ' você pode definir a variável de índice no seuv-for ' :) Eu amo isso por causa dessas joias.
Valentine Shi
@Edmundo Rodrigues Obrigado. Foi realmente bom. Eu estava apenas excluindo com o índice em vez do índice do objeto. muito obrigado
priya_21
62

Você também pode usar. $ Delete:

remove (index) {
 this.$delete(this.finds, index)
}

fontes:

Katinka Hesselink
fonte
4
Este é o caminho certo, pois avise a Vue das novidades.
insignar
1
por que está escrito na documentação "você raramente deve precisar usá-lo", é uma boa prática?
Miguel Stevens
@Notflip: normalmente você apenas substituirá o array como um todo.
Katinka Hesselink
1
por que essa não é a resposta aceita, quando array.splice não funciona em vue? @Gijsberts
yellowsir
1
@Roberto slice e splice são diferentes :)
Evil Pigeon
26

Não se esqueça de ligar atributo de chave, caso contrário sempre o último item será excluído

Maneira correta de excluir o item selecionado da matriz:

Modelo

<div v-for="(item, index) in items" :key="item.id">
  <input v-model="item.value">
   <button @click="deleteItem(index)">
  delete
</button>

roteiro

deleteItem(index) {
  this.items.splice(index, 1); \\OR   this.$delete(this.items,index)
 \\both will do the same
}
Afraz Ahmad
fonte
Esta realmente deve ser a resposta selecionada. Eu estava me perguntando por que nenhuma das opções (splice ou $ delete) estava funcionando e descobri que simplesmente não tinha um conjunto de chaves adequado.
Lunyx
Bem, definitivamente deletou alguma coisa, mas começou a fazer coisas estranhas quando a ligação ainda não estava no lugar.
DZet
1
Passei 4 horas me perguntando por que o último elemento sempre foi excluído. Obrigado por isso!
Carol-Theodor Pelu
6

É ainda mais engraçado quando você está fazendo isso com entradas, porque elas devem ser vinculadas. Se você estiver interessado em como fazer isso no Vue2 com opções para inserir e excluir, veja um exemplo:

por favor dê uma olhada no js violino

new Vue({
  el: '#app',
  data: {
    finds: [] 
  },
  methods: {
    addFind: function () {
      this.finds.push({ value: 'def' });
    },
    deleteFind: function (index) {
      console.log(index);
      console.log(this.finds);
      this.finds.splice(index, 1);
    }
  }
});
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div id="app">
  <h1>Finds</h1>
  <div v-for="(find, index) in finds">
    <input v-model="find.value">
    <button @click="deleteFind(index)">
      delete
    </button>
  </div>
  
  <button @click="addFind">
    New Find
  </button>
  
  <pre>{{ $data }}</pre>
</div>

Yevgeniy Afanasyev
fonte
isso é útil, mas você pode me ajudar nisso? Eu fiquei travado ao usar o componente .. codepen.io/wall-e/pen/dQrmpE?editors=1010
w411 3 de
3

Você pode deletar o item através do id

<button @click="deleteEvent(event.id)">Delete</button>

Dentro do seu código JS

deleteEvent(id){
  this.events = this.events.filter((e)=>e.id !== id )
}

O Vue envolve os métodos de mutação de uma matriz observada para que eles também acionem atualizações de visualização. Clique aqui para mais detalhes.

Você pode pensar que isso fará com que o Vue jogue fora o DOM existente e renderize novamente a lista inteira - felizmente, esse não é o caso.

Masum Billah
fonte
1
<v-btn color="info" @click="eliminarTarea(item.id)">Eliminar</v-btn>

E para o seu JS:

this.listaTareas = this.listaTareas.filter(i=>i.id != id)
Claudio Scheuermann
fonte
1
Sua resposta é quase igual às outras e não melhor do que outras. Então não vale a pena postar isso.
foxiris
0

Splice é o melhor para remover elemento de um índice específico. O exemplo fornecido é testado no console.

card = [1, 2, 3, 4];
card.splice(1,1);  // [2]
card   // (3) [1, 3, 4]
splice(startingIndex, totalNumberOfElements)

startupIndex começa em 0.

Kaushik Shrimali
fonte
0

Por que não omitir o método todos juntos, como:

v-for="(event, index) in events"
...
<button ... @click="$delete(events, index)">
James Jones
fonte