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

NVDA屏幕阅读器无障碍问题:切换锚点时读取双标签

NVDA无障碍阅读器切换锚点标签时重复读取内容的问题

问题现象

使用NVDA无障碍屏幕阅读器切换锚点标签(Knowledge和Support)时,会同时读出两个标签内容。比如从激活的Knowledge切换到Support,或反向切换时,本该只读取当前切换到的标签,实际却两个都读。但用Tab/Shift+Tab切换时读取正常。已尝试更换Chrome扩展阅读器、添加TabIndex、使用aria-labelledby属性等方案,问题仍未解决。

问题代码分析

当前代码逻辑存在冗余:针对每个scope状态(Knowledge/Support)都渲染了两组锚点标签,导致切换时DOM元素的替换可能触发NVDA的重复读取。比如当scope为Knowledge时,页面上同时存在激活状态的Knowledge锚点和未激活的Support锚点;切换到Support时,原有的两个锚点被替换成另外两个,NVDA可能在DOM更新过程中捕捉到了多个元素的变化。

原代码片段:

<div class="my-toggle-bar">
  <a *ngIf="mode == 'inbox' && scope == 'Knowledge'" aria-label="Knowledge filter button active" href="javascript:void(0)"
     (click)="changeScope('Knowledge')"
     [ngClass]="{'active': scope == 'Knowledge'}"
     class="active">                 
     <span>Knowledge</span>
  </a>
  <a *ngIf="mode == 'inbox' && scope == 'Support'" aria-label="Knowledge filter button" href="javascript:void(0)"
     (click)="changeScope('Knowledge')"
     [ngClass]="{'active': scope == 'Knowledge'}"
     class="active">                 
     <span>Knowledge</span>
  </a>
  <a *ngIf="mode == 'inbox' && scope == 'Knowledge'" aria-label="Support filter button" href="javascript:void(0)"
     [ngClass]="{'active': scope == 'Support'}"
     (click)="changeScope('Support')">
     <span>Support</span>
  </a>
  <a *ngIf="mode == 'inbox' && scope == 'Support'" aria-label="Support filter button active" href="javascript:void(0)"
    [ngClass]="{'active': scope == 'Support'}"
    (click)="changeScope('Support')">
    <span>Support</span>
  </a>
</div>

解决方案

简化DOM结构,只保留两个锚点标签,通过动态绑定控制激活状态和aria-label,避免切换时DOM元素的频繁替换:

<div class="my-toggle-bar">
  <a *ngIf="mode == 'inbox'" 
     [aria-label]="scope == 'Knowledge' ? 'Knowledge filter button active' : 'Knowledge filter button'"
     href="javascript:void(0)"
     (click)="changeScope('Knowledge')"
     [ngClass]="{'active': scope == 'Knowledge'}">                 
     <span>Knowledge</span>
  </a>
  <a *ngIf="mode == 'inbox'" 
     [aria-label]="scope == 'Support' ? 'Support filter button active' : 'Support filter button'"
     href="javascript:void(0)"
     (click)="changeScope('Support')"
     [ngClass]="{'active': scope == 'Support'}">
     <span>Support</span>
  </a>
</div>

优化说明

  • 移除冗余的*ngIf判断,每个标签只保留一个实例,通过动态绑定控制状态
  • 用[aria-label]根据当前scope动态设置标签文本,替代原有的多个静态aria-label
  • 激活状态通过[ngClass]动态切换,无需重复渲染相同元素
  • 减少DOM更新频次,避免NVDA在元素替换时读取到多个内容

额外建议

  • 避免使用javascript:void(0),可以将<a>改为<button>元素,更符合按钮交互的语义,无障碍支持更好
  • 如果必须使用<a>,确保添加role="button"属性,明确交互类型

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 14:53:13