You need to enable JavaScript to run this app. 在React中如何实现两个列表项的selected类名互斥切换
优惠活动
大模型
产品
解决方案
定价
更多

在React中如何实现两个列表项的selected类名互斥切换

无序列表单选选中排他效果实现方案

这个需求是典型的同组选项单选逻辑,核心要实现的就是「选中新项时自动清除其他项的旧选中状态」,不需要依赖任何第三方库,用原生JS就能完成,还能同步更新你代码里预留的aria-selected可访问属性,适配屏幕阅读器的识别逻辑。

核心实现思路

  • 监听列表项的点击事件
  • 触发点击时,先清空同组内所有元素的selected类名和对应的选中属性
  • 单独给当前被点击的列表项添加selected类名和对应的选中属性

注意点:不建议直接用item.className = 'selected'的方式赋值,这种写法会完全覆盖元素上原有的所有类名,优先使用classList系列方法操作类名,不会误伤其他已有样式类。

基础版完整实现

这个版本适合列表项数量固定、后续不会动态增减的场景,直接给每个li绑定点击事件即可:

<style>
/* 自定义selected类的展示样式,方便直观看到效果 */
li.selected {
  color: #1677ff;
  font-weight: 600;
}
</style>

<ul>
  <li role="option" aria-selected="false">
    yes
  </li>
  <li role="option" aria-selected="false">
    no
  </li>
</ul>

<script>
// 获取所有带option角色的li元素
const allOptions = document.querySelectorAll('ul li[role="option"]')

allOptions.forEach(option => {
  option.addEventListener('click', function() {
    // 遍历清除所有选项的选中状态
    allOptions.forEach(item => {
      item.classList.remove('selected')
      item.setAttribute('aria-selected', 'false')
    })
    // 给当前点击的选项设置选中状态
    this.classList.add('selected')
    this.setAttribute('aria-selected', 'true')
  })
})
</script>

优化版(事件委托实现)

如果你的列表项后续会通过接口动态加载、动态增删,给每个li单独绑定事件会有不必要的性能损耗,这时候可以把事件绑定在父级ul上,利用事件冒泡机制统一处理点击逻辑,后续新增的li元素不需要重新绑定事件就能自动适配交互:

const listContainer = document.querySelector('ul')

listContainer.addEventListener('click', function(e) {
  // 判断当前点击的元素是不是选项li
  const targetOption = e.target.closest('li[role="option"]')
  if (!targetOption) return

  // 清除当前组内所有旧的选中状态
  this.querySelectorAll('li.selected').forEach(item => {
    item.classList.remove('selected')
    item.setAttribute('aria-selected', 'false')
  })
  // 给当前点击的选项设置选中
  targetOption.classList.add('selected')
  targetOption.setAttribute('aria-selected', 'true')
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.22 09:15:05