最可靠的方式是用 JavaScript 切换 class 或 data- 属性,因纯 CSS 无法持久记录点击状态;推荐用 classList.toggle() 或 toggleAttribute(),配合语义化 CSS 选择器,并注意移动端兼容性与框架项目中应以状态驱动样式。

点击后用 JavaScript 切换 class 最可靠
纯 CSS 无法记住点击状态,:active 只响应按下瞬间,:visited 仅对链接有效且不适用于列表项。必须用 JavaScript 监听点击并切换 class。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 给
<ul></ul>或<ol></ol>加一个唯一id(如id="item-list"),避免污染全局事件 - 用
classList.toggle()而非className = ...,防止覆盖已有 class - 样式定义在 CSS 中,不要写内联
style,便于维护和复用
<ul id="item-list">
<li>第一项</li>
<li>第二项</li>
</ul>
<p><script>
document.getElementById('item-list').addEventListener('click', e => {
if (e.target.tagName === 'LI') {
e.target.classList.toggle('selected');
}
});
</script></p><p><style>
.selected { background-color: #cce5ff; }
</style>用 data- 属性管理多选状态更灵活
如果需要支持多选、取消、或后续读取哪些项被选中,直接操作 class 不够结构化。改用 data-selected 属性更清晰。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 初始不设
data-selected,点击时用hasAttribute()判断,再用toggleAttribute()切换 - CSS 用属性选择器匹配:
li[data-selected],比 class 更语义明确 - 后续遍历所有选中项只需
document.querySelectorAll('li[data-selected]')
<style>
li[data-selected] { background-color: #d4edda; color: #155724; }
</style>
<p><script>
document.getElementById('item-list').addEventListener('click', e => {
if (e.target.tagName === 'LI') {
e.target.toggleAttribute('data-selected');
}
});</script>移动端要注意 click 延迟和误触
在 iOS 和部分 Android 上,click 事件有约 300ms 延迟,且 <li> 默认不是可聚焦元素,可能影响可访问性。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 加
tabindex="0"让<li>可键盘聚焦,同时兼容屏幕阅读器 - 用
touchstart替代click消除延迟(但注意别和click重复触发) - 加
cursor: pointer提示用户该项可交互,尤其在桌面端
<li tabindex="0">可聚焦的项</li>
<p><style>
li { cursor: pointer; }
</style>React/Vue 等框架里别手动操作 DOM
如果你在用 React,直接用 useState 管理列表项的选中状态数组;Vue 用 v-bind:class 绑定动态 class。硬写 addEventListener 会绕过框架响应式,导致视图与状态不一致。
常见错误现象:
- 点击变色了,但重新渲染后颜色消失
- 控制台报错
Cannot read property 'addEventListener' of null(DOM 节点已被卸载) - 列表项是动态生成的(比如来自 API),手动绑定事件没处理新增节点
核心原则:框架项目里,状态驱动样式,而不是样式反推状态。


















