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

Vue 3 Swiper组件删除项时屏幕阅读器误播报全部aria标签问题

问题解决:Vue3 Swiper删除航班后屏幕阅读器误播报所有剩余卡片标签

问题原因分析

出现该问题的核心原因有两点:

  • Swiper的A11y模块执行update()时,会重新遍历所有slide元素;你的slide设置了role="heading"、tabindex="0"和动态aria-label,DOM更新后屏幕阅读器会自动读取这些带语义角色/可聚焦元素的aria信息,导致先播报所有剩余卡片的标签。
  • 确认消息的播报时机早于Swiper更新,因此被后续的Swiper元素播报延后。

解决方案

1. 调整Slide的ARIA属性,移除不必要的语义标记

slide仅作为容器存在,无需设置role="heading"和tabindex="0",交互核心放在删除按钮上即可。修改后的slide代码:

<swiper-slide 
  v-for="flight in savedFlights" 
  :id="`swiper-slide-${flight.id}`" 
  ref="swiperSlideRef" 
  :key="flight.id"
>
  <v-card class="flight-card" max-width="400">
    <v-img class="align-end" height="140" :src="flight.image" cover>
      <i 
        role="button" 
        :aria-label="`${ariaLabels.delFlight} ${flight.id}`" 
        tabindex="0"
        class="fa-sharp fa-solid fa-xmark color-white close-icon font-12 cursor-pointer"
        @click="removeFlight(flight.id,flight)" 
        @keydown.enter="removeFlight(flight.id, flight)"
      ></i>
    </v-img>
    <!-- 其他卡片内容 -->
  </v-card>
</swiper-slide>

2. 调整确认消息播报时机,确保在Swiper更新完成后执行

将确认消息播报移到nextTick回调内,等Swiper完成DOM更新后再触发,避免被Swiper的A11y播报打断:

const removeFlight = (id, flight) => {
  const originalLength = savedFlights.value.length;
  savedFlights.value = savedFlights.value.filter(item => item.id !== id);
  emit('savedFlightsLength', savedFlights.value);
  
  nextTick(() => {
    updateSwiper();
    const text = `${t('flight')} ${flight.id} ${t('of')} ${originalLength} ${t('removed')}. ${t('savedFlightTotal')}: ${savedFlights.value.length}`;
    announceToScreenReader(text);
  });
};

3. 优化屏幕阅读器播报函数,简化逻辑

提前在模板中添加live区域,避免动态创建的时机问题,同时移除不必要的延迟:

<!-- 在组件模板根元素外添加live区域 -->
<div id="sr-announcer" aria-live="polite" aria-atomic="true" class="sr-only"></div>
const announceToScreenReader = (message) => {
  const announcer = document.getElementById('sr-announcer');
  if (announcer) {
    // 先清空再赋值,确保aria-atomic生效
    announcer.textContent = '';
    announcer.textContent = message;
  }
};

4. 可选:自定义Swiper的A11y配置,禁用自动播报

如果上述调整后仍有问题,可在Swiper初始化时关闭不必要的自动播报:

const swiperOptions = {
  modules: [Navigation, Pagination, Scrollbar, A11y, Keyboard],
  a11y: {
    slideLabelMessage: null, // 禁用slide切换时的自动播报
    slideRole: 'group' // 将slide的role改为group,弱化语义优先级
  }
};

关键说明

  • 移除slide的tabindex="0"和role="heading"是核心:这些属性会让屏幕阅读器将每个slide视为独立的可聚焦/语义元素,DOM更新时会逐一读取。
  • 延迟确认消息到Swiper更新后,能确保播报顺序符合预期,不会被Swiper的DOM更新触发的播报打断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 00:03:10