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

如何在嵌套列表的无子项元素上隐藏箭头图标?

问题

我有一个包含若干元素的嵌套列表,目前每个列表项都会显示一个箭头图标,但存在问题:即使某个项没有子元素,箭头仍会显示。以下是列表项组件(CodeItem)的代码(为便于阅读已省略className):

function CodeItem({ props }: CodeItemProps) {
  const cpvs = Object.keys(tree) as Array<CpvLabelKey>;
  const [open, setOpen] = React.useState(cpvs.some(c => codes.includes(c)));
  
  return (
    <div>
      <fieldset>
        <div >
          <button
            onClick={() => setOpen(!open)}
            aria-expanded={open}
          >
             // this icon should be displayed only if Item has sub-elements
            <UilAngleRight/>
          </button>
          <input
            type="checkbox"
            name={`cpv-${code}`}
            id={`cpv-${code}`}
            checked={checked}
            onChange={e => onChange(e.target.checked, code)}
          />
        </div>

        <label htmlFor={`cpv-${code}`}>
          {code} - {tCPV(code)}
        </label>
      </fieldset>

      // where I map each Item
      {open && (
        <div>
          {cpvs.map(code => (
            <CodeItem
              key={code}
              code={code}
              onChange={onChange}
              tree={tree[code]?.children || {}}
              checked={codes.includes(code)}
              codes={codes}
            />
          ))}
        </div>
      )}
    </div>
  );
}
解决方案

核心思路是根据当前项是否存在子元素,条件渲染箭头按钮:

  1. 利用cpvs.length > 0判断是否有子元素(cpvs是当前项子元素的key集合,长度大于0则说明存在子元素)
  2. 仅当存在子元素时,渲染箭头按钮及其点击逻辑;无子女元素则不渲染该按钮

修改后的完整代码:

function CodeItem({ props }: CodeItemProps) {
  const cpvs = Object.keys(tree) as Array<CpvLabelKey>;
  const hasChildren = cpvs.length > 0; // 新增:判断是否有子元素
  const [open, setOpen] = React.useState(cpvs.some(c => codes.includes(c)));
  
  return (
    <div>
      <fieldset>
        <div >
          {/* 仅当有子元素时才渲染箭头按钮 */}
          {hasChildren && (
            <button
              onClick={() => setOpen(!open)}
              aria-expanded={open}
            >
              <UilAngleRight/>
            </button>
          )}
          <input
            type="checkbox"
            name={`cpv-${code}`}
            id={`cpv-${code}`}
            checked={checked}
            onChange={e => onChange(e.target.checked, code)}
          />
        </div>

        <label htmlFor={`cpv-${code}`}>
          {code} - {tCPV(code)}
        </label>
      </fieldset>

      {open && hasChildren && ( // 优化:无子女时不渲染空div
        <div>
          {cpvs.map(code => (
            <CodeItem
              key={code}
              code={code}
              onChange={onChange}
              tree={tree[code]?.children || {}}
              checked={codes.includes(code)}
              codes={codes}
            />
          ))}
        </div>
      )}
    </div>
  );
}

额外优化说明:

  • 在渲染子元素列表时增加hasChildren判断,避免无子女元素时生成冗余的空<div>标签
  • 无障碍属性aria-expanded仅在有子元素的按钮上存在,符合无障碍设计规范

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 09:23:06