繁体   English   中英

React Router browserHistory.push 在新标签页中打开链接

[英]React Router browserHistory.push open link in a new tab

可以使用<link>作为

<Link to="route" target="_blank">

在新标签页中打开链接。 但是是否可以使用browserHistory.push在新选项卡中打开链接?

React-router 是建立在浏览器历史 API 之上的。 browserHistory.push调用pushState()方法。

从链接文档的第一行:

pushState() 接受三个参数:状态对象、标题(当前被忽略)和(可选)统一资源定位符(URL)。

所以,你的问题的答案是“不”。

我已经抱怨了一个小时,直到我看到 Cooper 的评论

browserHistory 是每个标签。

这非常简单但准确,让我想出了这个解决方案:

我把它放在我的 App.js 中(更新:我添加了窗口blur事件,因为当 cmd+tab 或 cmd+` 到另一个窗口时我遇到了一个缺少的 keyUp 事件。)

  const [metaKeyPressed, setMetaKeyPressed] = useState(false);
  const handleMetaKeyDown = e => {
    if (e.metaKey) {
      setMetaKeyPressed(true);
    }
  };

  const handleMetaKeyUp = e => {
    if (e.metaKey) {
      setMetaKeyPressed(false);
    }
  };

  useEffect(() => {
    document.addEventListener('keydown', handleMetaKeyDown);
    document.addEventListener('keyup', handleMetaKeyUp);
    window.addEventListener('blur', handleMetaKeyUp);
    return () => {
      document.removeEventListener('keydown', handleMetaKeyDown);
      document.removeEventListener('keyup', handleMetaKeyUp);
      window.removeEventListener('blur', handleMetaKeyUp);
    };
  });

然后我有metaKeyPressed ,我用它来选择是history.push还是window.open (为了可读性而简化):

const handleRoute = path => { 
    if (metaKeyPressed) {
      window.open(path);
    } else {
      history.push(path);
    }
  };

另外,考虑为这个问题添加一个修复https://www.jitbit.com/alexblog/256-targetblank---the-most-underestimated-vulnerability-ever/我没有添加这个,因为浏览器想要用户当我这样做时明确允许弹出窗口。

基于 David 的回答,这可以通过将 useHistory 钩子包装在自定义钩子中来实现。 我将我的“useCtrlHistory”重命名为:

import {useEffect, useState} from 'react';
import {useHistory} from "react-router";

export default () => {

  const [ctrlKeyPressed, setCtrlKeyPressed] = useState(false);
  const handleKeyDown = e => {
    if (e.ctrlKey) {
      setCtrlKeyPressed(true);
    }
  };

  const handleKeyUp = e => {
    if (!e.ctrlKey) {
      setCtrlKeyPressed(false);
    }
  };

  const history = useHistory();

  let ctrlHistory = Object.assign({}, history, {
    push: (value) => {
      if (ctrlKeyPressed) {
        window.open(value);
      } else {
        history.push(value);
      }
    }
  });

  useEffect(() => {
    document.addEventListener('keydown', handleKeyDown);
    document.addEventListener('keyup', handleKeyUp);
    window.addEventListener('blur', handleKeyUp);
    return () => {
      document.removeEventListener('keydown', handleKeyDown);
      document.removeEventListener('keyup', handleKeyUp);
      window.removeEventListener('blur', handleKeyUp);
    };
  }, []);

  return ctrlHistory;
};

这将创建一个新的钩子来监听要按下的 ctrl 键。 用 useCtrlHistory.push 替换任何存在 useHistory.push 的实例,它将检测到 ctrl 键按下。

从 react_router 1.0 开始,props 将被传递到锚标签上。 您可以直接使用 target="_blank"。 在这里讨论: https : //github.com/ReactTraining/react-router/issues/2188

暂无
暂无

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

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