反应 16.9.0“javascript:;” href替代品? [复制]

Posted

技术标签:

【中文标题】反应 16.9.0“javascript:;” href替代品? [复制]【英文标题】:React 16.9.0 "javascript:;" href alternative? [duplicate] 【发布时间】: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 的 *** 问题,你们中的大多数人似乎都同意 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 【参考方案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 组件来管理不同的行为是个好主意,比如跟踪、路由、样式等。

以上是关于反应 16.9.0“javascript:;” href替代品? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

初识JavaScript

javascript 反应中的反应

javascript 反应页面转换(假设反应路由器v4)

以Vue为例,解释JavaScript的反应性

在 RCTBridgeModule.h 中反应本机重新定义“RCTMethodInfo”

df -h 卡住/没反应