繁体   English   中英

React SPA 中的锚点或按钮?

[英]Anchor or Button in React SPA?

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

在这种情况下,它应该是带有#href属性的传统锚链接还是按钮?

选项 1

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

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

选项 2

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

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

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

简短的回答

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

更简单地说:如果 URL 发生变化,或者您向页面添加大量信息,请使用超链接。

长答案

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

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

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

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

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

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

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

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

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

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

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

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

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

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

最好的方法是为每个具有tabindex="-1"的页面添加一个级别 1 标题 ( <h1> )。

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

这有两个好处:

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

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

单击<NavLink>时,您只需执行e.preventDefault()即可。 然后导航。 NavLink在 HTML 中生成<a>标签,并在路由处于活动状态时默认提供active class。 这允许您设置活动 state 链接的样式。

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

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

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

还有更多细节

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM