How to update Vue components when deleting a list item?

I know how to remove a list item from a Vue instance. However, when list items are passed to Vue components, how do I remove a list item while keeping the components in sync with the list?

Here is a usage example. Consider the online forum with the Markdown editor. We have a Vue instance, the data of which is a list of saved comments received from the server. These comments should be recorded in Markdowns.

For ease of editing and preview, we also have a list of components. Each component contains an editable input buffer, as well as a preview section. The contents of the saved comment in the Vue instance are used to initialize the input buffer and reset when the user cancels editing. A preview is a conversion of the contents of the input buffer.

The following is a test implementation:

<template id="comment">
    <div>
        Component:
        <textarea v-model="input_buffer" v-if="editing"></textarea>
        {{ preview }}
        <button type="button" v-on:click="edit" v-if="!editing">edit</button>
        <button type="button" v-on:click="remove" v-if="!editing">remove</button>
        <button type="button" v-on:click="cancel" v-if="editing">cancel</button>
    </div>
</template>

<div id="app">
    <ol>
        <li v-for="(comment, index) in comments">
            <div>Instance: {{comment}}</div>
            <comment
                v-bind:comment="comment"
                v-bind:index="index"
                v-on:remove="remove">
            </comment>
        </li>
    </ol>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.8/vue.js"></script>

<script>
let comments = ['111', '222', '333']

Vue.component('comment', {
  template: '#comment',
  props: ['comment', 'index'],
  data: function() {
    return {
      input_buffer: '',
      editing: false,
    }
  },
  mounted: function() { this.cancel() },
  computed: {
    preview: function() {
      // This is supposed to be a transformation of the input buffer,
      // but for now, let simply output the input buffer
      return this.input_buffer
    },
  },
  methods: {
    edit:   function() { this.editing = true },
    remove: function() { this.$emit('remove', this.index) },
    cancel: function() { this.input_buffer = this.comment; this.editing = false },
    //save: function() {},  // submit to server; not implemented yet
  },
})

let app = new Vue({
  el: '#app',
  data: { comments: comments },
  methods: {
    remove: function(index) { this.comments.splice(index, 1); app.$forceUpdate() },
  },
})
</script>

The problem is that if we delete the comment, the components will not be updated accordingly. For example, we have 3 comments in the above implementation. if you delete comment 2, a preview of paragraph 3 will still display the contents of paragraph 2. It is updated only if we click editand then cancel.

app.$forceUpdate(), .

+4
1

key v-for, :

<li v-for="(comment, index) in comments" :key="comment">

. : https://fiddle.jshell.net/mimani/zLrLvqke/

Vue , , .

. key.

+2

Source: https://habr.com/ru/post/1669854/


All Articles