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

购物清单开发问题:新项编辑绑定与首行复选框禁用

TodoList 两个问题的解决方案

问题1:点击新增行复选框时首行复选框联动勾选的解决方法

问题根源

所有复选框的id都设为item_name_check,但HTML规范要求id必须唯一。点击新增行的<label>时,for属性会匹配页面中第一个该id的元素(即首行复选框),导致联动勾选。

修复步骤

  1. 修改初始HTML里的首行复选框id为item_check_0,对应label的for属性同步更新;
  2. 在createItem函数中,利用全局id变量生成唯一的复选框id(如item_check_${id}),确保每个新项的复选框和label一一对应。

问题2:新增项目无法编辑的解决方法

问题根源

原代码仅给页面加载时存在的第一个.item_edit按钮绑定了事件,后续通过innerHTML新增的按钮未绑定事件;同时全局itemName变量始终指向首行文本元素,无法对应新增项。

修复步骤

采用事件委托机制,给父元素.items绑定点击事件,统一处理所有编辑按钮的交互:

  1. 删除原有的editBTN变量及对应的事件监听;
  2. 在.items的点击事件中,判断点击目标是否为编辑按钮;
  3. 针对当前点击项的.item_name元素单独处理编辑逻辑,避免全局变量干扰。

修改后的完整代码

HTML代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>TodoList</title>
  <script src="script.js" defer></script>
  <script src="https://kit.fontawesome.com/dde5490d2b.js" crossorigin="anonymous"></script>
  <link rel="stylesheet" href="style.css" />
</head>
<body>
  <section class="list">
    <header class="header">Shopping List</header>
    <ul class="items">
      <li class="item_row" data-id="0">
        <div class="item">
          <input type="checkbox" id="item_check_0" value="1"/>
          <label for="item_check_0" class="item_name">Egg</label>
          <div class="button_container">
            <button class="item_edit">Edit</button>
            <button class="item_delete">
              <i class="fas fa-trash-can" data-id="0"></i>
            </button>
          </div>
        </div>
        <div class="item_divider"></div>
      </li>
    </ul>
    <form class="new_form">
      <footer class="footer">
        <input type="text" class="footer_input" />
        <button type="submit" class="footer_button">
          <i class="fas fa-plus"></i>
        </button>
      </footer>
    </form>
  </section>
</body>
</html>

JS代码

const items = document.querySelector('.items');
const input = document.querySelector('.footer_input');
const form = document.querySelector('.new_form');

form.addEventListener('submit', (event) => {
  event.preventDefault();
  onAdd();
});

function onAdd() {
  const text = input.value;
  if (text === '') {
    input.focus();
    return;
  }
  const item = createItem(text);
  items.appendChild(item);
  item.scrollIntoView({ block: 'center' });
  input.value = '';
  input.focus();
}

let id = 1; // 首行已使用id=0,从1开始计数
function createItem(text) {
  const itemRow = document.createElement('li');
  itemRow.setAttribute('class', 'item_row');
  itemRow.setAttribute('data-id', id);
  const checkboxId = `item_check_${id}`;
  itemRow.innerHTML = `
    <div class="item">
      <input type="checkbox" id="${checkboxId}" value="1"/>
      <label for="${checkboxId}" class="item_name">${text}</label>
      <div class="button_container">
            <button class="item_edit" >Edit</button>
            <button class="item_delete" >
                <i class="fas fa-trash-alt" data-id=${id}></i>
            </button>
      </div>
    </div>
    <div class="item_divider"></div>`;
  id++;
  return itemRow;
}

items.addEventListener('click', (event) => {
  const target = event.target;
  
  // 处理删除逻辑
  const deleteIcon = target.closest('.fas.fa-trash-alt');
  if (deleteIcon) {
    const id = deleteIcon.dataset.id;
    const toBeDeleted = document.querySelector(`.item_row[data-id="${id}"]`);
    toBeDeleted.remove();
    return;
  }

  // 处理编辑逻辑
  const editBtn = target.closest('.item_edit');
  if (editBtn) {
    const itemName = editBtn.closest('.item').querySelector('.item_name');
    if (editBtn.innerText === 'Update') {
      const input = itemName.querySelector('.newItemInput');
      itemName.innerText = input.value;
      editBtn.innerText = 'Edit';
    } else {
      const currentText = itemName.innerText;
      itemName.innerHTML = '';
      const newItemInput = document.createElement('input');
      newItemInput.type = 'text';
      newItemInput.className = 'newItemInput';
      newItemInput.value = currentText;
      itemName.appendChild(newItemInput);
      newItemInput.focus();
      editBtn.innerText = 'Update';
    }
  }
});

内容的提问来源于stack exchange,提问作者Chocolate covered Strawberry

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 03:30:02