代码之家  ›  专栏  ›  技术社区  ›  Clocher Zhong

在v-for组件中删除了错误的项[选择正确的项:在v-for中键入]

  •  0
  • Clocher Zhong  · 技术社区  · 6 年前

    我有两个组件,如下所示:

         Vue.component('comp-child', {
             template: `<div>{{childData.name}}<slot></slot>{{randomNum}}</div>`,
             props: {
                 parentData: {
                 }
             },
             data() {
                 return {
                     childData: {},
                     randomNum: Math.round(Math.random() * 100)
                 };
             },
             created() {
                 this.childData.name = this.parentData.name;
             }
         });
         Vue.component('comp-parent', {
             template: `<div><component v-for="(item, index) in arr" is="comp-child" :key="index" :parent-data="item">
                 <button @click="deleteItem(index)">delete</button>
             </component>
             </div>`,
             data(){
                 return {
                     arr: [{
                         name:1
                     }, {
                         name:2
                     }, {
                         name:3
                     }, {
                         name:4
                     }, {
                         name:5
                     }]
                 };
             },
             methods: {
                 deleteItem(index) {
                     this.arr.splice(index, 1);
                     console.log(`${index}th element deleted! `);
                   
                 }
             }
         });
         let app = new Vue({
             el: '#app'
         });
    <script src="https://unpkg.com/vue"></script>
    
    <div id="app">
        <comp-parent></comp-parent>
    </div>

    在本演示中,无论您单击哪个项目,最后一个项目都将被删除。

    我发现这个问题是由 key 属于 v-for ,如果使用 1, 2, 3, 4,.. 作为键,这个问题发生了,但使用其他值作为键,如字符串,它只是工作良好;

    template: `<div><component v-for="(item, index) in arr" is="comp-child" :key="item.key" :parent-data="item">
                 <button @click="deleteItem(index)">delete</button>
             </component>
             </div>`,
             data(){
                 return {
                     arr: [{
                         name:1,
                         key: 'key1'
                     }, {
                         name:2,
                         key: 'key2'
                     }, {
                         name:3,
                         key: 'key3'
                     }, {
                         name:4,
                         key: 'key4'
                     }, {
                         name:5,
                         key: 'key5'
                     }]
                 };
             },
    

    检查这个小提琴: demo

    是虚拟DOM引起的吗?当 arr 更改后,它只是按索引(1,2,3,…)的顺序重新呈现组件,如果 阿里尔 被删除,长度为 阿里尔 减少,因为最后一个无法渲染。

    请有人给我解释一下,谢谢!

    1 回复  |  直到 6 年前
        1
  •  0
  •   bbsimonbb    6 年前

    当你使用v-for时, 您的密钥必须是某个特定于所讨论项目的数据片段 . 索引不好,因为它无法识别项。只需将键更改为item.name,示例就可以完美工作。

    在您的示例中,源数组被正确修改,但vue正在重用以前生成的组件实例来显示修改后的数组,这些实例已保留状态。Vue这样做是出于性能方面的原因,这通常不是问题,但它确实强调了选择正确密钥的重要性。

    你的问题因为一些你在自然界中不常看到的小事而变得更糟,你可能应该避免。。。在创建的钩子中将parentData.name分配给childData.name:由于您的子项被重用而不是重新创建,childData.name变得过时。随机数也是如此。

    Vue.component('comp-child', {
             template: `<div>{{childData.name}}<slot></slot>{{randomNum}}</div>`,
             props: {
                 parentData: {
                 }
             },
             data() {
                 return {
                     childData: {},
                     randomNum: Math.round(Math.random() * 100)
                 };
             },
             created() {
                 this.childData.name = this.parentData.name;
             }
         });
         Vue.component('comp-parent', {
             template: `<div><component v-for="(item, index) in arr" is="comp-child" :key="item.name" :parent-data="item">
                 <button @click="deleteItem(index)">delete</button>
             </component>
             </div>`,
             data(){
                 return {
                     arr: [{
                         name:1
                     }, {
                         name:2
                     }, {
                         name:3
                     }, {
                         name:4
                     }, {
                         name:5
                     }]
                 };
             },
             methods: {
                 deleteItem(index) {
                     this.arr.splice(index, 1);
                     console.log(`${index}th element deleted! `);
                   
                 }
             }
         });
         let app = new Vue({
             el: '#app'
         });
    <script src="https://unpkg.com/vue"></script>
    
    <div id="app">
        <comp-parent></comp-parent>
    </div>
    推荐文章