如何解决 jsx-a11y/no-static-element-interactions 限制?

How to work around jsx-a11y/no-static-element-interactions restriction?

我使用以下 jsx 在 FAQ table 中构建了一个条目:

  <li key={faqKey} className={styles.entry} onClick={handleExpandFn}>
    <div>
      <span className={`icon-next ${questionClassname}`} />
      <span className={styles['question-text']}>{faqEntry.question}</span>
    </div>
    {faqEntry.answer}
  </li>

这个想法是,当用户点击条目时,它会切换条目的打开状态。换句话说,当用户点击打开的 FAQ 条目时,它将关闭它。否则会打开。

但是 li 标签触发了这个 eslint 违规:Visible, non-interactive elements should not have mouse or keyboard event listeners jsx-a11y/no-static-element-interactions

不幸的是,我认为没有其他方法可以替代上述 html 标记。 由于是jsx,所以也不允许override如// eslint-disable-line jsx-a11y/no-static-element-interactions(行内注释会打印到网页)

那么我该如何解决呢?很高兴使用不同的 jsx 标记或 jsx eslint 覆盖

我记得的一个解决方案是使用带有 tab-index 的锚元素。

<a style={{display: 'list-item'}} tabIndex={-42} key={faqKey} className={styles.entry} onClick={handleExpandFn}>
  <div>
    <span className={`icon-next ${questionClassname}`} />
    <span className={styles['question-text']}>{faqEntry.question}</span>
  </div>
  {faqEntry.answer}
</a>

我没有将常见问题 table 的实现与 collapse/expand 交互功能滚动,而是用 react-collapsible 替换它。

它当然摆脱了 jsx-a11y/no-static-element-interactions 作为结果。

您可以按照以下方法修改标记以使其在语义上合适,并使 onclick 关闭 <li>

<li key={faqKey} className={styles.entry}>
  <h3>
    <button type='button' onClick={handleExpandFn}>
      <span className={`icon-next ${questionClassname}`} />
      <span className={styles['question-text']}>{faqEntry.question}</span>
    </button>
  </h3>
  <div className='add_a_panel_class_name_here'>
    {faqEntry.answer}
  </div>
</li>

以上内容: <h3> 将使按标题导航的 reader 用户可以轻松搜索常见问题解答的标题

<button> 放在 <h3> 内,可以为您提供适当的元素来附加点击事件(您想在此处使用按钮,因为您正在切换状态。<a> 如果您要转到新页面,则应使用。您也不需要将 tabindex 添加到按钮,因为它们本质上是可聚焦的)。

您可能还需要执行一些额外的步骤,使用按钮上的 ARIA 扩展和控件属性,但以上内容应该可以让您为克服错误打下良好的基础。

您实际上可以在 JSX 中添加 eslint 覆盖作为注释。 您必须将注释嵌套在大括号 {} 内,以便它被解释为 JavaScript。那么,当然,既然是JavaScript注释,就不会在JSX中渲染了。

根据您的风格偏好,您可以直接在代码之前的行中进行

{/* eslint-disable-next-line */}
<li key={faqKey} className={styles.entry} onClick={handleExpandFn}>

或者,在同一行的末尾

<li key={faqKey} className={styles.entry} onClick={handleExpandFn}> {/* eslint-disable-line */}

查看 docs 了解有关在 JSX 中使用 JavaScript 的更多信息。

你可以把 eslint-disable-line 放在 jsx

  <li // eslint-disable-line jsx-a11y/no-static-element-interactions
    key={faqKey} 
    className={styles.entry} 
    onClick={handleExpandFn}
   >
    <div>
      <span className={`icon-next ${questionClassname}`} />
      <span className={styles['question-text']}>{faqEntry.question}</span>
    </div>
    {faqEntry.answer}
  </li>

另一个选项,添加role='presentation'

  <li 
    key={faqKey} 
    className={styles.entry} 
    onClick={handleExpandFn} 
    role='presentation'
  >
    <div>
      <span className={`icon-next ${questionClassname}`} />
      <span className={styles['question-text']}>{faqEntry.question}</span>
    </div>
    {faqEntry.answer}
  </li>

对于那些正在寻找解决方法的人,请在您的代码中使用 role="presentation"

如果您尝试使用 li 实现菜单,那么正确的解决方案是在 li 标签中使用 role="menuitem"。 更多详情:https://w3c.github.io/aria/#menuitem

使用

aria-hidden="true"

在非交互元素标签上。喜欢

<span aria-hidden="true" onClick={() => void}>Text</span>

克服或避免 ES Lint 中的这个错误。

您可以根据自己的需要和要求使用三样东西

aria-hidden="true" - will remove the entire element from the accessibility API
role= "presentation" - The presentation role is used to remove semantic meaning from an element and any of its related child elements.
role= "none" - will remove the semantic meaning of an element while still exposing it to assistive technology. 

也有限制:

  1. 隐藏辅助技术的内容
  2. 不能用于可聚焦
  3. 元素不能用于交互元素的父元素