说明
客户端组件和服务端组件是两种组件类型.本文尽可能不涉及相关内容
通过文件系统定义路由
app目录下 页面所处的路径就是它的路由
仅存在page.js或route.js的文件夹被视作合法路由,且两个文件至多存在一个.
page.js
该路由对应的页面内容.应当默认导出一个react组件
export default function Page(){
return <span>1</span>
}
浏览器访问它对应的路由时 这个组件会被展示
route.js
此文件说明它所处的路由是一个"api",用于处理http请求.
具有特殊含义的文件
除了page.js,route.js,每级路由中还存在一些具有特殊含义的文件.它们应当默认导出一个react组件.它们都不是必需的.
在访问本级路由时,这个结构会被完整的呈现.如果访问的子路由,则Page会被替换为子路由的完整结构,也包含它自己的Layout,Template等.
Layout和Template
- 必须存在一个root layout
app/layout.js必须存在 且应该具有这样的结构
export default function(props){
return (
<html>
<body>
{/* ... */}
</body>
</html>
)
}
- Layout和Template所提供的组件需要正确包裹Page
export default function Layout(props:{ children:ReactNode }){
return (
<span>{props.children}</span>
)
}
- Template总是会重建 而Layout不会
类似于
<Layout>
<Template key={routeParam}>{children}</Template>
</Layout>
跳转和重定向
- Link组件
用于替代a标签.可以进行预请求
import Link from 'next/link'
export default function Page() {
return <Link href="/dashboard">Dashboard</Link>
}
Link的默认行为是滚动到新页面的顶部.可以设置参数scroll=false禁用此行为.
- 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.push的默认行为也是滚动至新页面顶部,可以使用router.push('/dashboard',{scroll:false})禁用这一行为.
- 重定向
服务端组件中 使用redirect进行重定向
import { redirect } from 'next/navigation'
// 组件中
redirect('/login')
api路由:route.js
route.js用于next服务端处理http请求.它应当导出GET、POST等一个或多个与http方法同名的函数
export async function GET() {
const data = 'get'
return Response.json({ data })
}
更详细的内容查看文档
软导航
url变化时 浏览器进行的是'硬导航',整个页面重新渲染.而next进行的是软导航,可以只重新渲染变化的路由所对应的组件.这有利于上级路由保存state
特殊的路由结构
路由组
可以在不影响url的前提下组织路由.
尽管分组的路由不可达 但它的layout.js文件仍然会对它包含的所有页面生效
平行路由(插槽)
export default function Layout({
children,
team,
analytics,
}: {
children: React.ReactNode
analytics: React.ReactNode
team: React.ReactNode
}) {
return (
<>
{children}
{team}
{analytics}
</>
)
}
作用上可以理解为Layout的子组件.平行路由不会体现在url上,但是可以拥有自己的loading.js,error.js等.
平行路由也可以拥有自己的子路由
此时访问'/settings',@team插槽处于active,会相应地显示/app/@team/settings/page.js,但@analytics插槽的状态则不确定.如果是next的软导航 则保留之前的状态 否则显示default.js(没有则会404).
值得注意的是 Layout接受的children参数也可以理解为一个特殊的插槽@children,它在未激活时也需要一个default.js
拦截路由
直接访问'/photo'时会显示/photo的内容;但从'/feed'跳转至'photo'时,这个url会被拦截,改为显示feed/(..)photo的内容.拦截路由允许同一个url,具有不同的表现,可以用于创建Modal等.
拦截规则如下
(.)匹配同一级别的区段(..)匹配上一级的区段(..)(..)匹配上述两个级别的区段(...)匹配根目录中的区段app