如何处理SPA应用程序中的“在新页面中打开链接的意图”?

时间:2019-07-04 18:16:27

标签: javascript react-router

在我的(反应式)单页应用程序中,我有很多“内部链接”。这些链接通过使用路由器存储更改URL来起作用。 (Mobx +反应)。

由于html标准警告不要使用没有实际href的href,如果使用on_click事件,则应使用样式类似于链接的按钮。

这很好用。除了现在我希望改善使用之外,我希望允许消费者按下ctrl + click,鼠标中键或用户使用的深奥浏览器的任何键绑定,以“在新选项卡中打开链接”。

有没有办法让浏览器获得点击的“意图”? -即查看用户是否打算在新标签页中打开链接(按钮)?

如果正常单击链接,是否不允许用户重新加载页面?

或者从另一面来看:当单击相对URL并在同一窗口中打开的链接时,如何防止重新加载整个页面?

4 个答案:

答案 0 :(得分:0)

尝试使用链接,它可以同时起作用:

import {Link} from 'mobx-router';

答案 1 :(得分:0)

So .. React-router-dom具有一个称为“链接”的组件。哪个可以完美地处理此用例。.

这是从react-routerrepo复制的Link组件的代码段。

function isModifiedEvent(event) {
  return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
}

function LinkAnchor({ innerRef, navigate, onClick, ...rest }) {
  const { target } = rest;

  return (
    <a
      {...rest}
      ref={innerRef} // TODO: Use forwardRef instead
      onClick={event => {
        try {
          if (onClick) onClick(event);
        } catch (ex) {
          event.preventDefault();
          throw ex;
        }

        if (
          !event.defaultPrevented && // onClick prevented default
          event.button === 0 && // ignore everything but left clicks
          (!target || target === "_self") && // let browser handle "target=_blank" etc.
          !isModifiedEvent(event) // ignore clicks with modifier keys
        ) {
          event.preventDefault();
          navigate();
        }
      }}
    />
  );
}

您可以稍微修改一下此组件以适合您的用例。尝试将其设置为HOC,或者可以使用renderProps模式在此锚定链接内呈现您的内容

希望这会有所帮助。

答案 2 :(得分:0)

就像其他答案中所述,最简单的方法是在出现移位或控制时不阻止Default。但是,就我而言,另一个第三方组件(PatternFly)处理了实际的导航事件并实现了preventDefault,因此我不得不提出一个全局解决方案。

我通过在文档的捕获阶段停止事件传播来解决此问题。

这将停止自DOM之后的自定义链接事件(带有preventDefault调用),并使默认链接逻辑生效。

这是一个打字稿示例,如果链接是外部的,它也要考虑在内:

document.addEventListener('click', (event: MouseEvent) => {  
  const target = event.target;
  if (target instanceof Element
    && (target as Element).baseURI
    && !isExternalUrl((target as Element).baseURI)
  ) {
    if (event.ctrlKey || event.shiftKey) {
      event.stopPropagation();
    }
  }
}, true);

和isExternalUrl就像

function isExternalUrl (url: string): boolean {
  const host = window.location.hostname;

  // Initialize as Relative URL
  var linkHost = host;
  if (/^https?:\/\//.test(url)) {
    // Absolute URL.
    // The easy way to parse an URL, is to create <a> element.
    // @see: https://gist.github.com/jlong/2428561
    var parser = document.createElement('a');
    parser.href = url;
    linkHost = parser.hostname;
  }

  return host !== linkHost;
}

答案 3 :(得分:-1)

function Anchor(props) {
    const {href, children} = props;
    function handleClick(e) {
        if (e.ctrlKey || e.shiftKey || e.metaKey || e.altKey) return; // let the browser handle
        e.preventDefault(); // take over
        try {
            window.history.pushState(null, null, href);
        } catch {
            window.location.assign(href);
        }
    }
    return <a {...props} onClick={handleClick}>{children}</a>
}

用法,就像一个<a>标签:

<Anchor href="/other-page">Go to Other Page</Anchor>