React SPA 中的锚点或按钮?

IT技术 javascript html reactjs react-router accessibility
2021-04-06 21:08:19

假设页面上有一段文本(无论它的样式是否为“传统”链接或按钮),单击该文本后会转到带有新页面/URL 的新页面。但是导航以编程方式发生(例如,通过react-router使用历史 Web API)而不是硬 HTTP 刷新。

在这种情况下,它应该是一个传统的锚链接,带有href诸如#或 按钮之类的属性

选项 1

<a href="#" onClick={navigateToNextPage}>Link</a>

缺点是你有一个垃圾href属性。您可以删除它,但它不在 Tab 键顺序中,并且不会获得默认链接样式(尽管可以通过一次性样式克服这些问题)。此外,如果您复制链接,它将复制为#不正确的内容,并会被屏幕阅读器错误地解释。

选项2

<button onClick={navigateToNextPage}>Link</a>

这里的缺点是,如果您希望它看起来像传统链接,则需要应用自定义样式。此外,在我看来,它在某些方面确实像一个传统的链接。但这对屏幕阅读器来说会更好。

3个回答

我无法评论 React,但这里是 SPA 的正确方法,在 React 中实现它应该是微不足道的。

简答

<a>如果没有其他选项可用,请使用超链接 ( ) 在页面之间导航以及加载其他内容时。

更简单:如果 URL 更改或您向页面添加了大量信息,请使用超链接。

长答案

在您的问题中,您提到了 History API 和react-router.

出于这个原因,我假设该函数navigateToNextPage更改了 URL。

我还假设我可以通过在浏览器中输入该 URL 来直接访问该页面。

考虑到这些假设,您应该使用:-

<a href="new-page-url" onClick={navigateToNextPage}>Link</a>

显然,您会停止默认操作(e.preventDefault()或 React 等效操作)。

关于为什么要使用上述格式的几点:-

  1. 可访问性- 当我遇到带有屏幕阅读器的超链接时,我可以询问我的屏幕阅读器该链接会将我带到哪里,这令人放心,我不能用按钮做同样的事情。这就是为什么我没有使用#超链接而是添加了实际目的地。如果您看到href="#"它几乎总是表明使用了错误的元素或使用不当。在阅读您关于在导航之前执行操作的评论后,这仍然是完全有效的,执行您的操作然后重定向,它仍然是一天结束时的导航。
  2. 可访问性- 当我通过屏幕阅读器浏览网站时,我可能决定循环浏览页面上的所有超链接以了解页面结构。例如,NVDA modifier+K获取下一个链接)。我不太可能遍历页面上的所有按钮来查找导航。
  3. 可访问性- 如果我遇到一个链接,我希望页面会发生变化(即使是通过 AJAX)。如果我遇到一个按钮,我希望它在当前页面上执行一个操作预期行为是可访问性的关键部分。
  4. 可访问性- 超链接有一些重要的状态。“已访问”是包含大量链接的页面上的关键内容,因为我可能想查看我之前阅读过的内容并能够通过访问过的链接进行导航(例如,所有未访问过的链接NVDA modifier+ K)。按钮不公开此信息。这里重要的一点是,您也不能button:visited在 CSS 中为按钮设置样式,因此您会错过那里每个人的视觉线索。
  5. 可访问性-Space关键与Enter关键。如果我登陆一个我希望按下space导航的链接,a<button>只能与Enter键一起使用,所以我可能会对页面没有改变的原因感到困惑。(我假设此时您已经使用了很多aria来说服我这个按钮是一个超链接)。
  6. 健壮性- 如果您的网站JavaScript 失败功能有限那么超链接远比按钮好。JavaScript 失败它仍然可以工作,这JavaScript 失败可能只是一个页面的临时加载问题特别有用,允许用户访问另一个功能页面。
  7. SEO - 我敢在 Stack Overflow 上谈论 SEO?耻辱!耻辱!耻辱!:-P - 但说真的,虽然谷歌在 JS 驱动的网站上可以做的事情非常聪明,但它仍然很难弄清楚 JavaScript 链接将把它带到哪里。如果 SEO 对您很重要,则使用带有有效目的地的超链接,以便 Google 可以正确映射信息。

可能还有其他原因我忘了提及,但我想我已经说明了这一点。

使用 AJAX 在页面之间导航时需要考虑什么?

虽然不是你问题的一部分,但我想我会很快补充几点以确保完整性。

如果您使用的是 SPA 模式(因此会中断正常导航),则需要向用户发出正在加载页面的信号。例如,我单击您的链接时,您需要让我知道正在执行某个操作(正在加载.....),因为您拦截了正常的浏览器行为e.preventDefault()或等效行为

最简单的方法是aria-live=assertive在解释页面正在加载的区域上使用您可以谷歌如何正确实施。

此外,当新页面加载时,您需要管理焦点。

执行此操作的最佳方法是向<h1>具有tabindex="-1".

页面加载后,您在 JavaScript 导航功能中执行的最后一个操作就是将焦点放在此标题上。

这有两个好处:

  1. 它让用户知道他们现在在哪里
  2. 它还让他们知道页面加载何时完成(因为 AJAX 导航不会在大多数屏幕阅读器中显示页面何时加载)。

使用tabindex="-1"它意味着标题不会被 JavaScript 以外的任何东西聚焦,因此不会干扰正常的文档流。

没问题,很高兴我能帮上忙!
2021-05-27 21:08:19
喜欢你的回答。
2021-06-19 21:08:19
爱爱爱它!正是我要找的 - 谢谢!
2021-06-20 21:08:19

你可以e.preventDefault()在点击<NavLink>做你的事情做。然后导航。当路由处于活动状态时,在 HTML 中NavLink生成<a>标签并active默认提供类。这允许您设置活动状态链接的样式。

import React from "react";
import { NavLink, withRouter } from "react-router-dom";

function Header(props) {
  const handleClick = e => {
    e.preventDefault();
    console.log("DO SOMETHING");
    props.history.push(e.target.pathname);
  };
  return (
    <ul>
      <li>
        <NavLink exact to="/" onClick={handleClick}>
          Home
        </NavLink>
      </li>
      <li>
        <NavLink to="/about" onClick={handleClick}>
          About
        </NavLink>
      </li>
      <li>
        <NavLink to="/topics" onClick={handleClick}>
          NavLink
        </NavLink>
      </li>
    </ul>
  );
}

export const HeaderNav = withRouter(Header);

工作示例:https ://codesandbox.io/s/react-router-5-rqzqq

我认为您投了反对票,因为它没有回答是使用按钮还是超链接。对我来说似乎有点苛刻,因为有人可以评论这个让你修复它。
2021-05-22 21:08:19
我不明白投反对票的原因。它解决了问题?
2021-06-02 21:08:19
这似乎只是解释。如果这是因为它不仅仅是苛刻的原因,那么它是一件很糟糕的事情。随着<NavLink>生成<a>HTML和包含active在该路线,只要你想,让你可以样式类时。我提供了工作示例¯_(ツ)_/¯
2021-06-19 21:08:19

我建议您使用语义 HTML。这意味着尽可能将正确的 HTML 元素用于其预期目的。

  1. 更容易开发——你可以免费获得一些功能,而且它可以说更容易理解。
  2. 在移动设备上更好——语义 HTML 可以说比非语义意大利面条代码在文件大小上更轻,并且更容易做出响应。
  3. 有利于 SEO — 搜索引擎更重视标题、链接等中的关键字,而不是非语义等中包含的关键字,因此客户更容易找到您的文档。

还有更多细节