网格布局中用事件委托处理卡片选中状态,核心是监听父容器点击事件,通过e.target.closest('.card')安全获取目标卡片并切换selected类,支持Ctrl/Cmd多选和空格键键盘操作。

在网格布局中用事件委托处理卡片选中状态,核心是:**监听父容器的点击事件,通过事件对象的 target 判断是否点中了某张卡片,并动态切换其选中类名(如 selected),同时可配合 dataset 或其他属性管理状态**。
确保网格容器和卡片结构合理
父容器设为 display: grid,每张卡片是子元素,且有统一标识(如相同 class、或带 data-id):
<div id="card-grid" class="grid"> <div class="card" data-id="1">卡片 1</div> <div class="card" data-id="2">卡片 2</div> <div class="card" data-id="3">卡片 3</div> </div>
对应 CSS 示例:
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)))); gap: 12px; }
.card { padding: 16px; border: 1px solid #ddd; border-radius: 4px; cursor: pointer; }
.card.selected { background: #007bff; color: white; border-color: #007bff; }
绑定事件委托并识别目标卡片
给网格容器添加点击监听器,用 event.target 向上查找最近的卡片元素(避免点到卡片内文字或空隙时失效):
立即学习“Java免费学习笔记(深入)”;
- 用
closest('.card')安全获取被点击的卡片元素 - 若找到卡片,再判断当前是否已选中,决定添加或移除
selected类 - 可选:用
dataset.id获取唯一标识,用于后续逻辑(如提交选中 ID 列表)
const grid = document.getElementById('card-grid');
grid.addEventListener('click', (e) => {
const card = e.target.closest('.card');
if (!card) return;
card.classList.toggle('selected');
// 如需维护一个选中 ID 数组,可这样同步:
// const id = card.dataset.id;
// const isSelected = card.classList.contains('selected');
// if (isSelected) selectedIds.add(id);
// else selectedIds.delete(id);
});
支持多选 + 按住 Ctrl/Cmd 键扩展选择
若希望像文件管理器一样按 Ctrl(Windows/Linux)或 Meta(macOS)多选,可在 toggle 前加判断:
- 检测
e.ctrlKey或e.metaKey - 未按下时,先清除其他卡片的
selected类,再选中当前 - 按下时,只对当前卡片做
toggle
grid.addEventListener('click', (e) => {
const card = e.target.closest('.card');
if (!card) return;
if (e.ctrlKey || e.metaKey) {
card.classList.toggle('selected');
} else {
// 单选模式:先取消所有选中
grid.querySelectorAll('.card').forEach(c => c.classList.remove('selected'));
card.classList.add('selected');
}
});
可选:键盘支持(空格键切换选中)
提升可访问性,给卡片加 tabindex="0",监听 keydown 事件:
- 卡片需能获得焦点(
tabindex="0") - 监听
keydown,当按空格(key === ' ')时触发选中切换 - 注意阻止默认滚动行为(
e.preventDefault())
// HTML 中卡片加 tabindex:
// <div class="card" data-id="1" tabindex="0">卡片 1</div>
grid.addEventListener('keydown', (e) => {
if (e.key !== ' ') return;
const card = e.target.closest('.card');
if (card) {
e.preventDefault();
card.classList.toggle('selected');
}
});


















