当Next.js中的路由处于活动状态时,目标活动链接

Rub*_*uby 6 reactjs react-router next.js

如何像在React-Router-4中那样将Next.js中的活动Link作为目标?意思是,当活动链接的路由处于活动状态时,给活动链接一个类?

Rot*_*eti 85

基于useRouter钩子的简单解决方案:

import Link from "next/link";
import { useRouter } from "next/router";


export const MyNav = () => {

  const router = useRouter();

  return (
    <ul>
      <li className={router.pathname == "/" ? "active" : ""}>
        <Link href="/">home</Link>
      </li>
      <li className={router.pathname == "/about" ? "active" : ""}>
        <Link href="/about">about</Link>
      </li>
    </ul>
  );
};

Run Code Online (Sandbox Code Playgroud)

  • 如果您的链接指向像“&lt;Link href="/#about"&gt;”这样的锚点怎么办?您如何使其成为活动链接? (3认同)
  • @gurupalsingh我认为在这种情况下你可以使用 `router.pathname.startsWith("/about") ?“活跃”:“”` (3认同)

小智 17

usePathname() 如果您使用的是 Next 13,您现在可以使用hook执行以下操作:


import { usePathname} from 'next/navigation';

export default function Example() {
    
    const pathname = usePathname();

    return(
        <div>
            <a
                href="/welcome"
                className={pathname == "/welcome" ? 
                "active" : 
                ""
                }
            >
        </div>
    )
}

Run Code Online (Sandbox Code Playgroud)


小智 12

如果您想使用锚链接,请尝试此版本的 @Rotareti 代码:

import Link from "next/link";
import { useRouter } from "next/router";


export const MyNav = () => {

  const router = useRouter();

  return (
    <ul>
      <li className={router.asPath == "/#about" ? "active" : ""}>
        <Link href="#about">about</Link>
      </li>
    </ul>
  );
};
Run Code Online (Sandbox Code Playgroud)


Sam*_*adi 8

另一个支持asprop的最低版本:

import Link from "next/link";
import {withRouter} from "next/router";
import {Children} from "react";
import React from "react";

export default withRouter(({router, children, as, href, ...rest}) => (
   <Link {...rest} href={href} as={as}>
      {React.cloneElement(Children.only(children), {
         className: (router.asPath === href || router.asPath === as) ? `active` : null
      })}
   </Link>
));
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这个答案,如果你想保留孩子的课程并只是追加,请使用:className: router.asPath === href || router.asPath === as ? `${children.props.className} active`:children.props.className (3认同)

Dar*_*ert 6

首先,您需要有一个名为Link的组件,其临时属性为activeClassName

import { withRouter } from 'next/router'
import Link from 'next/link'
import React, { Children } from 'react'

const ActiveLink = ({ router, children, ...props }) => {
  const child = Children.only(children)

  let className = child.props.className || null
  if (router.pathname === props.href && props.activeClassName) {
    className = `${className !== null ? className : ''} ${props.activeClassName}`.trim()
  }

  delete props.activeClassName

  return <Link {...props}>{React.cloneElement(child, { className })}</Link>
}

export default withRouter(ActiveLink)
Run Code Online (Sandbox Code Playgroud)

然后,使用带有创建的组件链接和CSS选择器的导航栏:active来区分活动链接和非活动链接。

import Link from './Link'

export default () => (
  <nav>
    <style jsx>{`
      .active:after {
        content: ' (current page)';
      }
      .nav-link {
        text-decoration: none;
        padding: 10px;
        display: block;
      }
    `}</style>

    <ul>
      <li>
        <Link activeClassName='active' href='/'>
          <a className='nav-link home-link'>Home</a>
        </Link>
      </li>
      <li>
        <Link activeClassName='active' href='/about'>
          <a className='nav-link'>About</a>
        </Link>
      </li>
    </ul>
  </nav>
)
Run Code Online (Sandbox Code Playgroud)

之后,您可以在页面上实现导航栏:

import Nav from '../components/Nav'

export default () => (
  <div>
    <Nav />
    <p>Hello, I'm the home page</p>
  </div>
)
Run Code Online (Sandbox Code Playgroud)

此项工作原理的关键位于组件Link内部,我们将Link中的router.pathnamewith属性值与之进行比较href,如果该值与另一个属性匹配,则放置特定的className以使该链接看起来已激活。

参考:这里

  • 但是,如果您路由到像 www.example.com/blog/xyz 这样的嵌套链接,这个东西就不起作用。链接在嵌套链接中变为非活动状态。 (2认同)

Dom*_*nic 5

打字稿版本:

import React from 'react'
import Link, { LinkProps } from 'next/link'
import { useRouter } from 'next/router'

export interface NavLinkProps extends LinkProps {
  children: React.ReactElement
}

export function NavLink({ children, href, ...props }: NavLinkProps) {
  const router = useRouter()
  return (
    <Link href={href} {...props}>
      {router.pathname === href ? React.cloneElement(children, { 'data-active': true }) : children}
    </Link>
  )
}
Run Code Online (Sandbox Code Playgroud)

请注意,除非必要,否则我不会克隆孩子。


Dia*_*aBo 5

这是 ActiveLink 与NextJS的另一个版本(参见下面的结果图)

import { withRouter } from 'next/router';
import PropTypes from 'prop-types';
import React from 'react';

const ActiveLink = ({ router, href, isLeftSideBar = false, children }) => {
  const isCurrentPath = router.pathname === href || router.asPath === href;

  const handleClick = (e) => {
    e.preventDefault();
    router.push(href);
  };

  (function prefetchPages() {
    if (typeof window !== 'undefined') router.prefetch(router.pathname);
  })();

  const theme =
    settings.theme === THEMES.LIGHT && isLeftSideBar ? '#e65100' : '#ffeb3b';
  const color = isCurrentPath ? theme : '';

  return (
    <a
      href={href}
      onClick={handleClick}
      style={{
        textDecoration: 'none',
        margin: 16,
        padding: 0,
        fontWeight: isCurrentPath ? 'bold' : 'normal', // I left mine all bold
        fontSize: 17,
        color: isLeftSideBar ? '#e65100' : '#ffeb3b',
      }}>
      {children}
    </a>
  );
};

ActiveLink.propTypes = {
  href: PropTypes.string.isRequired,
  children: PropTypes.any,
};

export default withRouter(ActiveLink);
Run Code Online (Sandbox Code Playgroud)

随处调用

<ActiveLink href='/signup'> Sign Up </ActiveLink>
Run Code Online (Sandbox Code Playgroud)

结果

在此输入图像描述