当您想使用链接组件时,外部链接在 Next.js 中不起作用

Posted

技术标签:

【中文标题】当您想使用链接组件时,外部链接在 Next.js 中不起作用【英文标题】:External link is not working in Next.js when you want to use Link component 【发布时间】:2020-07-18 09:51:14 【问题描述】:

当您想在其中使用外部 URL 和 html Button tag 时,一个简单的 Link 组件在 Next.js 中不起作用,这让我感到非常惊讶。

你可以在下面看到我是如何解决这个问题的:

方法 1

<Link href="https://***.com/">
  <button>***</button>
</Link>

方法 2(无协议链接):

<Link href="//***.com/">
  <button>***</button>
</Link>

方法号 3(链接无协议且链接属性 prefetch 设置为 false 甚至 true):

<Link href="//***.com/" prefetch=false>
  <button>***</button>
</Link>

重要提示

当然,提到的情况是,当 URL 是内部的时它可以工作,就像这样:

<Link href="/***">
  <button>***</button>
</Link>

或者当我将 HTML 按钮标签更改为HTML A tag 时,像这样:

<Link href="//***.com/">
  <a>***</a>
</Link>

就我而言,我想在 Next.js Link 组件中使用 HTML 按钮标记或任何其他 UI 组件。

【问题讨论】:

【参考方案1】:

1. Next.js Link 组件内的 UI 组件解决方案。

我更详细地研究了 Next.js 文档,我发现了一个非常有用的属性,可以在 Link 组件中为任何内部 UI 组件(Semantic UI、Material UI、Reactstrap 等)创建外部链接。

让我们以一个简单的语义 UI 按钮组件为例。 要向 Next.js Link 组件添加外部链接,我们应该使用属性passHref。该属性默认设置为false。此属性强制 Link 将 href 属性发送给其子级。

import  Button  from 'semantic-ui-react';
import Link from 'next/link';    

const Example = () => (
  <Link href="https://***.com/" passHref=true>
    <Button>***</Button>
  </Link>
)

export default Example;

2。 HTML 元素的解决方案(与标签 A 不同)

在 Next.js 文档中,您可以找到以下句子

外部 URL,以及任何不需要路由导航的链接 使用/pages,不需要用Link处理;使用锚标签 代替这种情况。

而且我必须写它是显而易见的,所以在这种情况下,如果您需要使用任何其他标记,例如 HTML 按钮,您应该在没有链接组件的情况下使用onClick 事件。 上面的代码将如下所示:

const clickHandle = () => 
  document.location.href = 'https://***.com/';


const Example = () => (
  <button onClick=clickHandle>***</button>
)

export default Example;

更新: 当然,我同意开发人员的观点,他们认为对于外部链接我们不应该使用 Link 组件。这里最好的解决方案是在点击事件上仅使用纯 HTML a 标签或 JS 重定向解决方案,如第 2 点所示(或任何类似方式)。值得一提的是,您可以构建自己的组件,并基于传递的href 属性,您可以在Link 组件和HTML a 标签之间切换,如下所示:

  // custom simple smart Link component
  import Link from 'next/link'; 
  
  const SmartLink = (link, url) => 
    const regEx = /^http/;

    return regEx.test(url) ? <Link href=url>link</Link> : <a href=url>link</a>;
  
  
  export default SmartLink;

  // ways to call the component
  import SmartLink from 'path/to/SmartLink'; // set correct path

  // somewhere inside the render method
  // the below will use HTML A tag
  <SmartLink href="https://***.com" link="external *** website" />
  // the below will use Next.js Link component
  <SmartLink href="/***" link="internal *** page" />

【讨论】:

const URL = ( link ) =&gt; const type, url = link return ( &lt;ListItem style= width: "inherit", display: "inline-block" &gt; &lt;a href=url&gt; &lt;ListItemIcon&gt; Github: &lt;GitHub /&gt;, BitBucket: &lt;InsertLink /&gt;, GitLab: &lt;InsertLink /&gt;, ***: &lt;InsertLink /&gt;, LinkedIn: &lt;LinkedIn /&gt;, [type] &lt;/ListItemIcon&gt; &lt;/a&gt; &lt;/ListItem&gt; ) 这个@Mario Boss @SalahAdDin - 您应该使用 Next.js 中的 Link 组件并将 A 标签包装在其中: *** 链接> 酷,最重要的是在 URL 前加上一个// @SalahAdDin - 我很高兴这有效.. 一切顺利.. 在我看来,接受的答案是错误的。当 标签不是 的子标签时使用 passHref。对于外部 URL,只需使用不带 的 ,请参见下文。【参考方案2】:

Link 组件仅用于在 Next 应用中的页面之间进行链接。不支持传递外部 URL 的行为,并且应该给您一个链接到 this page 的错误,其中包括此部分:

为什么会出现这个错误

Next.js 提供了一个可以通过组件使用的路由器 通过 next/link 导入,一个带有Router(Component) 的包装器,现在是一个 挂钩用户路由器()。当使用其中任何一个时,预计它们是 仅用于内部导航,即在页面之间导航 相同的 Next.js 应用程序。

要么您将非内部 href 传递给 next/link 组件,要么您 称为 Router#push 或 Router#replace 。

无效的 href 包括外部网站 (https://google.com) 和 mailto: 链接。过去,这些无效的 href 的使用可能已经消失 被忽视,但因为它们可能导致意外行为。我们现在展示一个 警告他们正在开发中。

如果你在里面渲染一个&lt;a&gt;,href 会被传递给它,并使用本机浏览器行为按预期工作,但其他元素不能使用它,所以你必须自己处理这种情况。

我建议您查看您想要实现的目标 - 使用 &lt;a&gt; 标记有什么问题?这似乎是适合这项工作的工具。

【讨论】:

感谢您的回答,但是当您想使用自定义 UI 组件作为链接时,有很多示例。例如 Semantic-UI 中的 Button 组件。 @MarioBoss 看起来像按钮的东西和按钮组件之间是有区别的。 &lt;a&gt; 应该用于链接到不同的 URL(可能是不同的页面,或当前页面上的锚点),&lt;button&gt; 应该用于在页面上执行操作(其中 URL 没有改变)。如果您希望&lt;a&gt; 看起来像一个按钮,请将其设置为这样。使用语义用户界面,您可以&lt;a href="…" class="ui button"&gt;I look like a button&lt;/a&gt;【参考方案3】:

在我看来,接受的答案是错误的。当&lt;a&gt; 标签不是&lt;Link&gt; 的子标签时,使用passHref。对于外部 URL,只需使用 &lt;a&gt; 而不使用 &lt;Link&gt;,请参见下文。

  const link = props.link.charAt(0) === '/' ? <Link as=stripUrlPlaceholder(props.link) href="/">
    <a>image</a>
  </Link> : <a href=props.link rel="noreferrer" target="_blank">image</a>;

  return <div className="banner">
    link
  </div>;

【讨论】:

【参考方案4】:

对于外部链接,不需要使用 next/link,因为它只用于路由之间的客户端转换。链接不适用于在您的应用之外进行链接。

【讨论】:

【参考方案5】:

我遇到了同样的问题,不知何故我尝试了上述答案,但这并没有真正的帮助。我发现如果你添加 https 或 HTTP:// ,它肯定会自动允许你打开外部网络。这里是一个示例:

<a href=`https://$Your link`> Open external Link </a>

【讨论】:

【参考方案6】:

简单地说,使用&lt;a&gt; 标签而不是下一个&lt;Link&gt;。下一个&lt;Link&gt; 用于内部导航。

示例 1。

   <a
     href='https://www.facebook.com/queueunderstop/'
     target="_blank"
     rel="noreferrer">
       <Image
         className='gb'
         src='/images/icons/fb.png'
         alt='facebook'
         width=25
         height=25
       />
   </a>

这解决了链接打开新链接同时关闭主站点的问题。主要需要注意的是属性:

    target="_blank" rel="noreferrer"

我也尝试了各种组合,并在仔细阅读文档后确定了这一点,即使文档没有隐含地说。这些文件涵盖了更多的实际情况,而不是所有的假设。

【讨论】:

以上是关于当您想使用链接组件时,外部链接在 Next.js 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Next.js 的活动页面上设置链接组件的样式

当您的外部 SDK 只有 .dll、.lib、.h 文件时如何链接和构建项目

hbuilder mui 开发app, 打开外部链接,如何返回

Next.js 带有外部动态源的图像组件

如何跟踪 next.js 中的活动链接?

尝试将 FontAwesome 放入正文时出现 Next.js 链接错误