You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React任务复选框交互代码逻辑解析求助

代码逻辑逐行解析:Todo任务勾选/取消勾选的位置调整逻辑

下面我们一步步拆解这段代码的执行流程,重点解释你疑惑的「取消勾选倒数第二个任务会移到开头」的逻辑:

1. 复制并更新任务的勾选状态

const updatedTasks = tasks.map((task, i) =>
  i === index ? { ...task, checked: !task.checked } : task
);

这一步通过map遍历原任务数组,仅对点击的目标任务(索引为index的项)做状态翻转:如果原任务是勾选状态,就改成未勾选;反之则改成勾选。其他任务保持原样,最终得到状态更新后的新数组,此时任务位置还未调整。

2. 将目标任务移到数组末尾

updatedTasks.push(updatedTasks.splice(index, 1)[0]);

这里是关键的位置调整第一步:

  • splice(index, 1)会从updatedTasks中移除索引为index的目标任务,splice返回被移除元素组成的数组,所以[0]用于取出这个目标任务。
  • 再通过push把这个目标任务添加到数组的末尾。
    到这一步,不管是勾选还是取消勾选操作,目标任务都会被先移到数组最后。

3. 根据任务状态决定是否移到开头

if (!updatedTasks[updatedTasks.length - 1].checked) {
  updatedTasks.unshift(updatedTasks.pop());
}

这是你疑惑的核心逻辑:

  • 首先判断当前数组最后一个元素(也就是刚移过来的目标任务)的checked状态是否为false(即取消了勾选)。
  • 如果满足条件,就用pop()把最后一个元素(目标任务)移除,再通过unshift()把它添加到数组的开头。

针对「取消勾选倒数第二个已完成任务」的场景举例

假设原任务数组是这样(已完成任务checked: true):

tasks = [
  { text: "任务1", checked: false }, // 未完成
  { text: "任务2", checked: true }, // 已完成
  { text: "任务3", checked: true }, // 已完成,倒数第二个(你点击的目标)
  { text: "任务4", checked: true }  // 已完成,最后一个
];

执行流程如下:

  1. map之后,目标任务(任务3)的checked被翻转为false,数组变为:
[
  { text: "任务1", checked: false },
  { text: "任务2", checked: true },
  { text: "任务3", checked: false },
  { text: "任务4", checked: true }
];
  1. splice+push操作后,任务3被移到数组末尾:
[
  { text: "任务1", checked: false },
  { text: "任务2", checked: true },
  { text: "任务4", checked: true },
  { text: "任务3", checked: false }
];
  1. 检测到最后一个元素(任务3)的checked为false,执行pop+unshift,任务3被移到数组开头:
[
  { text: "任务3", checked: false },
  { text: "任务1", checked: false },
  { text: "任务2", checked: true },
  { text: "任务4", checked: true }
];

而勾选任务的场景中,目标任务的checked会被设为true,第三步的if条件不满足,所以任务会留在数组末尾,符合你的预期。

内容的提问来源于stack exchange,提问作者Nixy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 16:00:04