代码之家  ›  专栏  ›  技术社区  ›  Andy

从列表中删除vue组件始终删除列表中的最后一个元素

  •  2
  • Andy  · 技术社区  · 6 年前

    我已经阅读了使用v-for渲染列表中自定义组件的文档 here

    但由于某种原因,我无法让它工作。它总是删除最后一个组件,而不是我在索引中发送的组件。知道它为什么不起作用吗?

    我的VUE JS版本是:2.5.16。

    使用PHPStorm IDE并在docker(linux容器)上运行

    和Laravel mix(我有 “laravel mix”:“0。*” 包装中的条目。json)使用webpack并编译JS模块。

    这是我的一些代码

    // Parent Component JS
    <template>
        <ul>
            <li
                is="child-component"
                v-for="(child, index) in componentList"
                :key="index"
                :myVal="Something...."
                @remove="dropField(index)"
                @add-custom-field="addField"
            ></li>
        </ul>
    </template>
    
    <script>
        import childComponent from './ChildComponent';
    
        export default {
            name: 'CustomList',
    
            components: {'child-component' :childComponent},
    
              data() {
                return {
                    componentList: []
                }
              },
    
           methods: {
                addField() {
                    console.log('Handling add-custom-field  field...');
                    this.componentList.push(childComponent);
                },
    
                dropField(index) {
                    console.log(`I am deleting the component with index = ${index}  from listview in parent...`);
                    this.componentList.splice(index, 1); 
                }
            }
        }
    
    
    // Child Component JS
    
    <template>
        <div>
           <input type="text" v-model="currentValue" /><button @click.prevent="$emit('remove')" > Remove </button>
        </div
    </template>
    <script>
      export default {
         props: { myVal : '' },
         data() { return { currentValue: ''} },
         created() {this.currentValue = this.myVal;}
    
      }
    </script>
    
    2 回复  |  直到 6 年前
        1
  •  3
  •   Sphinx    6 年前

    问题是由 v-for的就地补丁策略 。这意味着当从componentList中删除一个元素时,Vue不会重建所有子级。

    检查 Vue Guide on an “in-place patch” strategy for v-for :

    当Vue更新使用v-for渲染的元素列表时,通过 默认情况下,它使用就地修补策略。如果数据的顺序 项已更改,而不是移动DOM元素以匹配 项目顺序,Vue将修补每个元素并确保 它反映了在该特定索引处应该呈现的内容。

    实际上,您已经删除了最后一项,但问题是数据属性=currentValue of first&第一次安装时,第二个孩子是“a”、“b”。稍后,当Vue重新渲染(删除最后一个子级)时,data property=currentValue保持相同的值,尽管prop=myVal已更改。

    看看下面的演示,我添加了一个输入并绑定了myVal,您将看到不同之处。

    Vue.config.productionTip = false
    
    let childComponent = Vue.component('child', {
      template: `<div class="item">
          <p>Index:{{parentIndex}} => <button @click.prevent="removed()" > Remove </button>
          Data:<input type="text" v-model="currentValue" />Props:<input type="text" v-bind:value="myVal" />
          </p>       
        </div>`,
         props: { 'myVal':{
              type: String,
              default: ''
            } ,
            'parentIndex': {
              type: Number,
              default: 0
            }
          },
         data() {
           return { 
            currentValue: ''
           } 
         },
         mounted() {
          this.currentValue = this.myVal
         },
         methods: {
          removed: function () {
            this.$emit('remove')
          }
         }
    })
    
    
    app = new Vue({
      el: "#app",
      data() {
        return {
            componentList: ['a', 'b', 'c'],
            componentType:childComponent
        }
      },
    
      methods: {
        addField() {
            console.log('Handling add-custom-field  field...');
            this.componentList.push(childComponent);
        },
    
        dropField(index) {
            console.log(`I am deleting the component with index = ${index}  from listview in parent...`);
            this.componentList.splice(index, 1); 
        }
      }
    })
    li:nth-child(odd) {
      background-color:#d0d5dd;
    }
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
    <div id="app">
        <ul>
            <li v-for="(child, index) in componentList"><div
                :is="componentType"
                :key="index"
                :my-val="child"
                :parent-index="index"
                @remove="dropField(index)"
                @add-custom-field="addField"
            >{{child}}</div></li>
        </ul>
    </div>
        2
  •  3
  •   A. Khaled    5 年前

    我发现如果你有另一个更新 :key 所有物 (非索引) 你想怎么做就怎么做

    这是我的例子

    <template>
        <div id="app">
            <ul>
                <li
                    v-for="(teacher, index) in teachers_list"
                    v-bind="teacher"
                    :key="teacher.id"
                >
                <p>Teacher id {{teacher.id}}</p>
                <button @click="deleteTeacher(index)"></button>
                </li>
            </ul>
        </div>
    </template>
    
    <script>
    export default {
        data() {
            return {
                    teachers_list: [
                    {name: 'teacher a', id: 100},
                    {name: 'teacher b', id: 200},
                    {name: 'teacher c', id: 300},
                ]
            }
        },
        methods: {
            deleteTeacher(index) {
                console.log(index);
    
                this.teachers_list.splice(index, 1)
            }
        }
    }
    </script>