next.js_路由

发布时间 2023-10-25 00:21:07作者: Steperouge

路由构建

  • acme.com/dashedboard/settings路由为例
    • 第一个/代表app目录
    • /dashboard代表app/dashboard目录
    • /dashboard/settings代表app/dashboard/settings目录
  • 访问acme.com/会自动访问app/page.js文件
  • 访问acme.com/dashedboard会自动访问到app/dashboard/page.js文件
  • 如果存在app/test空目录, 那么acme.com/test路径不可访问

layout.js

  • 如果一个目录中有layout.js目录, 那么对应的目录只会走layout.js文件, 而不会走page.js文件; 布局会包裹页面

  • layout.js中的基本设定

    • export default function RootLayout ({ children }) {
        return (
          <html lang="en">
            <body>
              {children}
              <div id="main"></div>
            </body>
          </html>
        )
      }
      
    • 有且只有layout.js文件中可以写入html与body标签, app目录下的layout.js中应该包含有html与body标签.

    • layout.js中的children, 在访问当前目录时引入的是page.js的结构; 在访问下级目录时引入的是下级目录的layout.js(下级目录的children引入的是同目录的page.js文件)

      1. 定义根布局

        1. export default function RootLayout ({ children }) {
            return (
              <html lang="en">
                <body>
                  <div id="mainLayout">
                    {children}
                  </div>
                </body>
              </html>
            )
          }
          
      2. 定义根页面

        1. export default function RootPage () {
            return (
              <div id="rootPage">
                <h1>这是根页面的结构</h1>
              </div>
            )
          }
          
      3. 访问/目录

        1. <div id="mainLayout">
              <div id="rootPage">
                  <h1>这是根页面的结构</h1>
              </div>
          </div>
          
      4. 定义test1目录的layout.js与page.js

        1. // /test1/page.js
          export default function Test1Page () {
            return (
              <div id="testPage">
                <h1>这是test1页面结构</h1>
              </div>
            )
          }
          
        2. // /test1/layout.js
          export default function Test1Layout ({ children }) {
            return (
              <div>
                {children}
                <div id="test1Layout"></div>
              </div>)
          }
          
        3. 访问/test1

          1. <div id="mainLayout">
                <div>
                    <div id="testPage">
                        <h1>这是test1页面结构</h1>		</div>
                 	<div id="test1Layout"></div>	</div>
            </div>
            

template.js

  • template.js写在与layout.js同级目录下, 如下所示: 在根目录下创建page.js,layout.js,template.js

  • // /app/page.js
    export default function RootPage () {
      return (
        <div id="rootPage">
          <h1>这是根页面的结构</h1>
        </div>
      )
    }
    
  • // /app/layout.js
    export default function RootLayout ({ children }) {
      return (
        <html lang="en">
          <body>
            <div id="rootLayout">
              {children}
            </div>
          </body>
        </html>
      )
    }
    
  • // /app/template.js
    export default function RootTemplate ({ children }) {
      return (
        <div id="rootTem1">
          {children}
        </div>
      )
    }
    
  • 访问/路径, 得到以下的html结构

    • <div id="rootLayout">
          <div id="rootTem1">
              <div id="rootPage">
                  <h1>这是根页面的结构</h1>
              </div>
          </div>
      </div>
      
  • /app/test1目录下编写以下几个文件

    • // /app/test1/page.js
      export default function Test1Page () {
        return (
          <div id="testPage">
            <h1>这是test1页面结构</h1>
          </div>
        )
      }
      
    • // /app/test1/layout.js
      export default function Test1Layout ({ children }) {
        return (
          <div id="test1Layout">
            {children}
          </div>)
      }
      
    • // /app/test1/template.js
      export default function Test1Template ({ children }) {
        return (
          <div id="test1Tem1">
            {children}
          </div>
        )
      }
      
  • 访问/test1路径, 得到以下结构

    • <div id="rootLayout">
          <div id="rootTem1">
              <div id="test1Layout">
                  <div id="test1Tem1">
                      <div id="testPage">
                          <h1>这是test1页面结构</h1>
                      </div>
                  </div>
              </div>
          </div>
      </div>
      

自定义head

  • 使用metadata定义页面的head内容, metadata只能在page.jslayout.js中使用

    • // /app/layout.js
      export const metadata = {
        title: 'root',
        description: 'root....'
      }
      
    • // /app/test1/layout.js
      export const metadata = {
        title: 'Test',
        description: 'Test....'
      }
      
    • 如此便实现了访问不同的目录有不同的标题

link组件

import Link from 'next/link'
 
export default function PostList({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>
          <Link href={`/blog/${post.slug}`}>{post.title}</Link>
        </li>
      ))}
    </ul>
  )
}

usePathname

  • 您可以使用usePathname()来确定链接是否处于活动状态。例如,要将类添加到活动链接,可以检查当前路径名是否与链接的href匹配:

  • 'use client'
     
    import { usePathname } from 'next/navigation'
    import Link from 'next/link'
     
    export function Links() {
      const pathname = usePathname()
     
      return (
        <nav>
          <ul>
            <li>
              <Link className={`link ${pathname === '/' ? 'active' : ''}`} href="/">
                Home
              </Link>
            </li>
            <li>
              <Link
                className={`link ${pathname === '/about' ? 'active' : ''}`}
                href="/about"
              >
                About
              </Link>
            </li>
          </ul>
        </nav>
      )
    }
    

滚动到指定锚点

<Link href="/dashboard#settings">Settings</Link>
 
// Output
<a href="/dashboard#settings">Settings</a>

useRouter

'use client'
 
import { useRouter } from 'next/navigation'
 
export default function Page() {
  const router = useRouter()
 
  return (
    <button type="button" onClick={() => router.push('/dashboard')}>
      Dashboard
    </button>
  )
}
  • router.pushrouter.replace

路由预取

  • <Link>组件:当路线在用户的视口中可见时,会自动预取这些路线。预取发生在页面首次加载时或通过滚动进入视图时。
  • router.prefetch():useRouter钩子可用于以编程方式预取路由。

路由组

  • /app/(student)/list
  • /app/(teacher)/list
  • 可以在(student)这些目录中添加layout.js等文件, 带括号的目录不会影响路由

创建多个根路由

  • 要创建多个根布局,请删除顶级layout.js文件,并在每个路由组中添加一个layout.js文件。这对于将应用程序划分为具有完全不同的UI或体验的部分非常有用。<html><body>标记需要添加到每个根布局中。

动态路由

  • 例如,博客可以包括以下路径,其中是博客文章的动态分段。app/blog/[slug]/page.js[slug]

  • export default function Page({ params }) {
      return <div>My Post: {params.slug}</div>
    }
    
  • 创建/app/template/[id]/page.js文件

    • export default function templatePage({params}){
        return (
          <div id="tem">{params.id}</div>
        )
      }
      
    • 访问/template/25, 页面成功打印25