next路由和文件系统

125 阅读4分钟

hello大家好,我是萝卜。之前一直想在公司项目里用next,但几乎没用过next, 而且工期又紧张,想着不保险几次都放弃了,着实可惜, 所以这次我打算认真系统的学习一下next,并且将我学习next的笔记记录输出出来,这样既提升了我的理解,也能给大家分享一些宝贵的学习经验,也欢迎大家在学习过程中,边学边输出,写自己的文章博客, 或者到评论留言。

课程资源

我比较喜欢看文档类的课程,因为相比于视频课程,节奏我可以更好的把控,另外我觉得看文字比听老师说效率高很多, 但光看官方文档我又觉得枯燥,而且不知从何下手,所以我找到了yayu的掘金小册,讲的比较细致的,例子也还算简单好上手

学习方法

yayu的小册内容总共80多节,我计划是每天看几节(根据内容多少),具体学习方法是先把整节快速过一遍看完,然后把重要的内容跟着敲一边,继续看下一节,最后把学习的内容总结成笔记,在写笔记的时候看一下内容大纲,并自己回忆思考,还可以添加一些自己思考。

今日笔记

话不多说,来写一份day1的笔记吧

快速启动next项目

使用next.js的cli的创建命令, 快速启动next项目,可以根据脚手架的提示自由选择项目配置, 这里yayu为了简单选的是js,而我选的ts,所以后面我会自己去加一些多ts的配置和代码,另外npm装包比较慢,我比较喜欢用pnpm, 所以包管理工具我是用pnpm,当然yarn和bun也很不错,看个人喜欢

  npx create-next-app@latest
  yarn create next-app
  pnpm create next-app
  bunx create-next-app

next项目目录结构

next从v13.4之后模板就是默认app目录了,因为app目录的功能性相比page目录更加强大。这是下载下来的项目目录结构:

project/
└── app
    ├── layout.js
    ├── ...
    └── page.js 

路由系统

next的app目录下的文件夹结构直接决定路由结构,比如有个文件夹结构是app/article/page.js,那么访问article页面就是url后面加/article, page就是react中的index,只是next换了个约定名称。

文件系统

next中每个app下的路由文件夹下有如下若干文件,名称都是约定好的: layout: 布局组件 template: 模板组件 error: 错误组件 not found: 404页面 loading: 加载组件 page: 页面功能组件

这些页面都是用来做什么的呢? 拿刚刚article路由举例,用户访问/article路由,如果路由输错了,那就显示404页面,加载有bug, 失败了就显示错误组件,这两个很好理解,

路由输入没问题,则先加载layout组件,再进入template组件,最后进入page组件,如果page有异步阻塞了,则会替换显示为loading组件,等待加载完成后再显示page。

具体来说,它们功能的区别: 拿一个文章列表页面举例, layout是公共布局,比如侧边栏,顶部栏,怎么切换子页面都不变的就放到这里面。 template也是布局,比如页面的标题,它的组件样式可以给子组件复用,但子组件的切换了, 它的内容和状态,包括useEffect也是需要重新加载的。 page是存放具体的内容和功能,比如文章详情。

error和404细节

error

先说一下error,看看文件层级

    <Layout>
      <Template>
        <ErrorBoundary fallback={<Error/>}>
          <Suspense>
            <ErrorBoundary fallback={<NotFound/>}>
              <Page />
            </ErrorBoundary> 
          </Suspense>   
        </ErrorBoundary>   
      </Template>   
    </Layout>  

Error这个页面是被layout和template包裹的,如果layout和template页面有错误, 就只能被上一层ErrorBoundary捕获了,如果到达顶层,就很尴尬,所以next提供了global-error来捕获全局错误,写到app目录下即可

404

404页面默认在app目录下写一个即可, 如果想在子路由中加入其他自定义的404组件,需要手动调用NotFound, 不调用默认还是会显示app目录下的404页面

import { notFound } from 'next/navigation'

export default function Page() {
  notFound()
  return <></>
}

疑问

为什么getData中不能使用setData更新dom?而是必须return data

export default  function Home() {
// const [data, setData] = useState<string>('');

const getData  = async () => {
  await new Promise<void>((resolve) => setTimeout(resolve, 1000))
  // 为什么getData中不能使用setData更新dom?而是必须return data
  return {
    data: '这是第一层pages'
  }
}

  // const {data} = await getData()
  const {data} = use(getData()) 
  return (
    <div>hello, {data}</div>
  );
}