← 返回目录

16. 实战:全选反选与已选计数

这是购物车全选的经典逻辑:顶框管所有子框子框反过来管顶框(用 every 判断是不是全选了)、反选实时数选了几个。核心就一个属性:复选框的 .checked(true 打勾 / false 没打勾)

16.1 实战(勾一勾试试)

已选中 0 件商品

勾一勾: 顶框管子框、 子框反推顶框, 下面同步代码与计数。

16.2 核心代码拆解

① 顶框控制所有子框

// 抓到顶框
let allCheck = document.getElementById('allCheck');

// 把所有子框抓出来
let itemList = document.querySelectorAll('.item');

// 顶框一勾或取消就跑
allCheck.addEventListener('change', function () {
  // 从第 0 个子框挨个走
  for (let i = 0; i < itemList.length; i++) {
    // 每个子框都跟顶框走
    itemList[i].checked = allCheck.checked;
  }

  // 打出来看看:true 是全勾
  console.log('顶框状态', allCheck.checked);
});

② 子框反过来管顶框(every 判断)

// 给每个子框都绑一遍
for (let i = 0; i < itemList.length; i++) {
  // 这次轮到的子框
  let oneItem = itemList[i];

  // 某个子框一改就跑
  oneItem.addEventListener('change', function () {
    // 先假设全勾
    let allChecked = true;

    // 挨个检查
    for (let j = 0; j < itemList.length; j++) {
      // 发现有一个没勾
      if (!itemList[j].checked) {
        // 那就不是全勾
        allChecked = false;
        // 不用再看后面的了
        break;
      }
    }

    // 把结果写回顶框
    allCheck.checked = allChecked;

    // 打出来看看
    console.log('是不是全勾', allChecked);
  });
}

如果你用错方法判断全选,顶框状态会不对。记住用 every——它是"每一个都满足才 true",正好表达"全部打勾"。

③ 反选 + 数个数

// 点反选按钮
reverseBtn.addEventListener('click', function () {
  // 挨个走每个子框
  for (let i = 0; i < itemList.length; i++) {
    // 打勾变不打、不打变打
    itemList[i].checked = !itemList[i].checked;
  }
});

// 数一下选了几个
function updateCount() {
  // 先从 0 开始数
  let num = 0;

  // 挨个看每个子框
  for (let i = 0; i < itemList.length; i++) {
    // 如果这个勾上了
    if (itemList[i].checked) {
      // 计数器加一
      num = num + 1;
    }
  }

  // 把数字显示出去
  count.textContent = num;

  // 打出来看看数对没
  console.log('已选', num);
}

实战:用在哪 / 常见坑 / 怎么解决

① 用在哪:购物车全选、批量操作、勾选审核。

② 常见坑:子框联动顶框判断写错;反选后顶框不同步。

③ 怎么解决:用 Array.every 判断是否全选;反选后重新同步顶框和计数。

一句话记住:.checked 读打没打勾;顶框遍历赋子框,子框用 every 反推顶框,反选取反,数个数用 filter 数 true。

本页重点

API作用参数返回值代码示例
元素.checked读/改打没打勾true/false布尔all.checked = true;
addEventListener('change')勾选变化时触发函数box.addEventListener('change', fn);
循环遍历子框逐个同步勾选状态for 循环for (let i = 0; i < list.length; i++) list[i].checked = true;