簡體   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