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

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

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

方法 1

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

方法 2(无协议链接):

<Link href="//stackoverflow.com/">
  <button>StackOverflow</button>
</Link>

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

<Link href="//stackoverflow.com/" prefetch={false}>
  <button>StackOverflow</button>
</Link>

重要提示

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

<Link href="/stackoverflow">
  <button>StackOverflow</button>
</Link>

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

<Link href="//stackoverflow.com/">
  <a>StackOverflow</a>
</Link>

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

【问题讨论】:

    标签: javascript html jsx next.js uicomponents


    【解决方案1】:

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

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

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

    import { Button } from 'semantic-ui-react';
    import Link from 'next/link';    
    
    const Example = () => (
      <Link href="https://stackoverflow.com/" passHref={true}>
        <Button>StackOverflow</Button>
      </Link>
    )
    
    export default Example;
    

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

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

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

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

    const clickHandle = () => {
      document.location.href = 'https://stackoverflow.com/';
    }
    
    const Example = () => (
      <button onClick={clickHandle}>StackOverflow</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://stackoverflow.com" link="external StackOverflow website" />
      // the below will use Next.js Link component
      <SmartLink href="/stackoverflow" link="internal StackOverflow 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;, StackOverflow: &lt;InsertLink /&gt;, LinkedIn: &lt;LinkedIn /&gt;, }[type] } &lt;/ListItemIcon&gt; &lt;/a&gt; &lt;/ListItem&gt; ) } 这个@Mario Boss
    • @SalahAdDin - 您应该使用 Next.js 中的 Link 组件并将 A 标签包装在其中: StackOverflow 链接>
    • 酷,最重要的是在 URL 前加上一个//
    • @SalahAdDin - 我很高兴这有效.. 一切顺利..
    【解决方案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>
          

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

          1. target={"_blank"}
          2. rel={"noreferrer"}

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

          【讨论】:

            猜你喜欢
            • 2021-04-15
            • 2021-11-04
            • 1970-01-01
            • 1970-01-01
            • 2017-02-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-08-24
            相关资源
            最近更新 更多