为什么Vue中的.splice()方法总是删除最后一个项目

3

更新:现在它正常工作了。老实说,我不确定自己做了什么——我真的不记得改变了任何东西,但我相信这是由于大家的反馈,所以感谢所有帮助过我的人。

我有一个循环,根据数组中的对象生成表格行。无论我触发删除操作的是哪一行,总是删除数组中的最后一项。

数据——存储为“meetingPlans”

[
  {
    dow:"-T-R---",
    endTime:"11:45:00",
    startTime:"08:45:00"
  },
  {
    dow:"--W----",
    endTime:"12:45:00",
    startTime:"10:45:00"
  },
  {
    dow:"----F--",
    endTime:"15:00:00",
    startTime:"14:00:00"
  }
]

模板

<tr v-for="(meetingPlan,meetingPlanIndex) in meetingPlans" :key="meetingPlanIndex">
    <td>
      -- stuff here doesn't matter --
    </td>
    <td>
        -- stuff here doesn't matter either --
    </td>
    <td class = "pl-0">
        <button v-on:click="removeMeetingPlan(meetingPlanIndex)" type = "button" class = "btn btn-danger btn-sm">
            <i class = "fas fa-times"></i>
        </button>
    </td>
</tr>

Vue代码

var vm = new Vue({
        el:"#dynamic-planning-column",
        delimiters:["<%","%>"],
        // This is defined server-side.  "meetingPlans" is one of the properties of planData
        data:window.planData,
        methods:{
            addReserveGroup:function(index){
                this.reserveGroups.push({number:'',description:'',cap:''});
            },
            removeReserveGroup:function(index){
                this.reserveGroups.splice(index,1);
            },
            addMeetingPlan:function(index){
                this.meetingPlans.push({id:0,dow:'',startTime:'',endTime:'',timeslot:-1});
            },
            removeMeetingPlan:function(index){
                this.meetingPlans.splice(index,1);
            },
            meetingPlanDowIsOdd:function(MeetingPlan){
                return MeetingPlan.dow.includes('M') || MeetingPlan.dow.includes('W') || MeetingPlan.dow.includes('F');
            }
        }
    });

对我来说,看起来应该能够工作。
尝试过的调试方式:
- 确保模板中的meetingPlanIndex是唯一值。 - 当我修改removeMeetingPlan()以输出index并输出this.meetingPlans[index]时,两个都是预期值。 - 当我修改removeMeetingPlan()为硬编码:this.meetingPlans.splice(0,1)时,它仍会删除最后一个项。
我尝试的解决方案是,我读到可以将:key设置为对象而不是数字,所以我修改了模板:
<tr v-for="(meetingPlan,meetingPlanIndex) in meetingPlans" :key="meetingPlan">

那样做可以成功删除正确的行,但是Vue会警告重复的键和使用非原始数据作为键。


还有什么其他尝试方法吗?


3
当你说“总是删除数组中的最后一个元素”时,你是如何确定的?这听起来像是你成功地修改了数组,但由于key的不当使用,更新后的数组没有被正确渲染。 - skirtle
1
我实际上无法重现这个问题,但是将对象转换为字符串不应该失败。 - ggorlen
1
将以下内容从英语翻译为中文:将“:key =” meetingPlanIndex“ ”更改为”:key =“ JSON.stringify(meetingPlan)”。 - Ohgodwhy
1
当我将removeMeetingPlan()修改为硬编码:his.meetingPlans.splice(0,1) - 它仍然删除了最后一个项目,再加上上面无效的meetingPlans定义(每个字段没有逗号分隔符),让我觉得你的数组有些异常。 - dispake
1
meetingPlans 声明在哪里?你能粘贴一下你的 data 函数吗? - Ross Allen
显示剩余10条评论
1个回答

1
我使用您提供的代码制作了一个示例 - 看起来运行良好。

Vue.component('meeting-plans', {
  data: function() {
    return {
      meetingPlans: [
        {
          dow: "-T-R---",
          endTime: "11:45:00",
          startTime: "08:45:00",
        },
        {
          dow: "--W----",
          endTime: "12:45:00",
          startTime: "10:45:00",
        },
        {
          dow: "----F--",
          endTime: "15:00:00",
          startTime: "14:00:00",
        }
      ],
    }
  },
  methods: {
    removeMeetingPlan: function(index) {
      this.meetingPlans.splice(index, 1);
    },
  },
  template: `
    <table>
      <tr v-for="(meetingPlan,meetingPlanIndex) in meetingPlans" :key="meetingPlanIndex">
        <td class="pl-0">
          <button v-on:click="removeMeetingPlan(meetingPlanIndex)" type="button" class="btn btn-danger btn-sm">
            Remove {{ meetingPlan.dow }}
          </button>
        </td>
      </tr>
    </table>
  `
})

new Vue({
  el: '#demo',
})
<div id="demo">
  <meeting-plans />
</div>

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


哎呀!对了,缺少逗号只是因为我抄写时的错误。已经修复了。 - Quasipickle
我能够立即看到的唯一区别是,(1)你创建了一个组件,而我只是使用了一个原始应用程序(即:var vm = new Vue({...}))。此外,你的数据是一个函数,而我的只是一个对象——但我认为这是由于组件/应用程序之间的差异引起的。这会产生任何显著的影响吗? - Quasipickle
2
(1) 我认为那不应该有影响。 (2) 可能是问题所在。数据必须是一个函数。https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function - Marc Barbeau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接