【问题标题】:React 16.9.0 "javascript:;" href alternative? [duplicate]反应 16.9.0“javascript:;” href替代品? [复制]
【发布时间】:2019-12-22 03:24:54
【问题描述】:

更新到 React 16.9.0 后,我收到了如下严重警告:

警告:未来版本的 React 将阻止 javascript: URL 作为安全预防措施。如果可以,请改用事件处理程序。如果您需要生成不安全的 HTML,请尝试使用 dangerouslySetInnerHTML。 React 通过了“javascript:;”。

它来自这样的代码:

const Component = ({someAction}) => (
  <a href="javascript:void(0)" onClick={someAction}>click me</a>
);

查看关于 HTML 中 which “href” value should I use for JavaScript links 的 StackOverflow 问题,你们中的大多数人似乎都同意 javascript:void(0) 是最好的选择,这在 React 16.9.0 中将不再可能。

仅用href="#" 替换是有问题的,因为浏览器会滚动到页面顶部并更改显示的 URL。特别是如果您使用哈希链接进行路由,这是非常有问题的。

我可以更新我的整个代码库以在每个事件处理程序中添加e.preventDefault();,但这似乎很难做到,尤其是当事件处理程序是从 Redux 操作创建者或挂钩自动创建时。我不会到处寻找“只包括e.preventDefault();”的答案!

还使用&lt;button&gt; 意味着我必须处理许多不需要的样式。

所以我想知道:是否有任何特定于库 React 的解决方案来获得一个有效的 &lt;a&gt; 链接,它只会触发一个没有副作用的操作?我想尽可能少地更改代码并摆脱弃用警告。

【问题讨论】:

  • @EmileBergeron 但我想避免一直手动调用e.preventDefault()
  • 如果你有那么多的按钮链接,我会选择按钮的方式。您甚至可以使用div,尽管这需要一些可访问性调整。
  • 如果它是一个永远不会用作链接的链接,它应该是一个按钮。
  • 是的,不要使用锚点作为按钮。对于语义标记和可访问性来说,这是一种不好的做法。
  • 已经有人质疑 react 团队添加这个警告的决定了:github.com/facebook/react/pull/15047#issuecomment-521736797

标签: javascript reactjs


【解决方案1】:

在反应blog post:

javascript: 开头的网址是危险的攻击面 因为很容易在标签中意外包含未经处理的输出 喜欢&lt;a href&gt; 并创建一个安全漏洞。

在 React 16.9 中,这种模式继续有效,但它会记录一个 警告。如果你使用javascript: URLs 进行逻辑,请尝试使用 React 事件 处理程序。

我个人更喜欢这样使用它: &lt;a href="#!" onClick={clickAction}&gt;Link&lt;/a&gt;

【讨论】:

  • 我已阅读博文。这仍然给我留下了以某种方式调用e.preventDefault() 的问题。
【解决方案2】:

我想出了一个这样的组件:

import React, {useCallback} from 'react';

function AHrefJavascript({ children, onClick, ...props }) {
  const handleClick = useCallback(
    e => {
      e.preventDefault();
      return onClick(e);
    },
    [onClick]
  );

  return (
    <a href="#javascript" {...props} onClick={handleClick}>
      {children}
    </a>
  );
}

它只会包装事件处理程序以创建一个新的也调用e.preventDefault() 的事件处理程序。它将向href 添加一个哈希链接,这不会触发弃用警告。当传入的处理程序更新时,使用钩子的功能它只会更改事件处理程序。一个问题是在浏览器中您仍然可以在新选项卡中打开此链接,因此它不如带有javascript:void(0) 的链接好,这会阻止这种情况。

使用方便,组件如下:

const Component = ({someAction}) => (
  <AHrefJavascript onClick={someAction}>click me</a>
);

因此,可能有人可以在整个项目中将a href="javascript:void(0)" 替换为AHrefJavascript,然后在各处添加组件的导入。

最后,也许最好的选择是使用 &lt;button&gt; 并通过箍来删除所有不需要的样式。

【讨论】:

  • 只调用e.preventDefault() 的组件似乎有点过头了,有时,您还想保留默认行为。虽然使用某种Link 组件来管理不同的行为是个好主意,比如跟踪、路由、样式等。
猜你喜欢
  • 1970-01-01
  • 2012-04-08
  • 1970-01-01
  • 2012-01-28
  • 2016-06-13
  • 2012-12-20
  • 1970-01-01
  • 2013-03-07
  • 1970-01-01
相关资源
最近更新 更多