美文网首页
NextJS入门之探索篇

NextJS入门之探索篇

作者: 硅谷干货 | 来源:发表于2023-04-10 22:13 被阅读0次

    简介

    Next.js 是一个轻量级的 React 服务端渲染应用框架。

    官网链接:www.nextjs.cn/

    优点:

    • 零配置

      自动编译并打包。从一开始就为生产环境而优化。

    • 混合模式: SSG 和 SSR

      在一个项目中同时支持构建时预渲染页面(SSG)和请求时渲染页面(SSR)

    • 增量静态生成

      在构建之后以增量的方式添加并更新静态预渲染的页面。

    • 支持 TypeScript

      自动配置并编译 TypeScript。

    • 快速刷新

      快速、可靠的实时编辑体验,已在 Facebook 级别的应用上规模上得到验证。

    • 基于文件系统的路由

      每个 pages 目录下的组件都是一条路由。

    • API 路由

      创建 API 端点(可选)以提供后端功能。

    • 内置支持CSS

      使用 CSS 模块创建组件级的样式。内置对 Sass 的支持。

    • 代码拆分和打包

      采用由 Google Chrome 小组创建的、并经过优化的打包和拆分算法。

    创建Next.js项目

    手动创建Next.js项目

    mkdir nextDemo //创建项目

    npm init //初始化项目

    npm i react react-dom next --save //添加依赖

    package.json中添加快捷键命令

     "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "dev" : "next" ,
        "build" : " next build",
        "start" : "next start"
      },
    复制代码
    

    创建pages文件夹和文件

    在项目根目录创建pages文件夹并在pages文件夹中创建index.js文件

    function Index(){
        return (
            <div>Hello Next.js</div>
        )
    }
    export default Index
    复制代码
    

    运行项目

    npm run dev

    creact-next-app快速创建项目

    create-next-app可以快速的创建Next.js项目,它就是一个脚手架。

    npm install -g create-next-app //全局安装脚手架

    create-next-app nextDemo //基于脚手架创建项目

    cd nextDemo

    npm run dev //运行项目

    目录结构介绍:

    • components文件夹: 这里是专门放置自己写的组件的,这里的组件不包括页面,指公用的或者有专门用途的组件。
    • node_modules文件夹:Next项目的所有依赖包都在这里,一般我们不会修改和编辑这里的内容。
    • pages文件夹:这里是放置页面的,这里边的内容会自动生成路由,并在服务器端渲染,渲染好后进行数据同步。
    • static文件夹: 这个是静态文件夹,比如项目需要的图片、图标和静态资源都可以放到这里。
    • .gitignore文件: 这个主要是控制git提交和上传文件的,简称就是忽略提交。
    • package.json文件:定义了项目所需要的文件和项目的配置信息(名称、版本和许可证),最主要的是使用npm install 就可以下载项目所需要的所有包。

    Pages

    在 Next.js 中,一个 page(页面) 就是一个从 .jsjsx.ts.tsx 文件导出(export)的 React 组件 ,这些文件存放在 pages 目录下。每个 page(页面)都使用其文件名作为路由(route)。

    如果你创建了一个命名为 pages/about.js 的文件并导出(export)一个如下所示的 React 组件,则可以通过 /about 路径进行访问。

    路由

    页面跳转一般有两种形式,第一种是利用标签<Link>,第二种是用js编程的方式进行跳转,也就是利用Router组件

    Link

    import React from 'react'
    import Link from 'next/link'
    
    
    const Home = () => (
      <>
        <div>我是首页</div>
        <div><Link href="/pageA"><a>去A页面</a></Link></div>
        <div><Link href="/pageB"><a>去B页面</a></Link></div>
    
      </>
    )
    
    export default Home
    复制代码
    

    注意:用<Link>标签进行跳转是非常容易的,但是又一个小坑需要你注意一下,就是他不支持兄弟标签并列的情况。

     //错误写法
     <div>
      <Link href="/pageA">
        <span>去A页面</span>
        <span>前端博客</span>
      </Link>
    </div>
    
    //正确写法
    <Link href="/pageA">
      <a>
        <span>去A页面</span>
        <span>前端博客</span>
      </a>
    </Link>
    复制代码
    

    Router

    import Router from 'next/router'
    
    <button onClick={()=>{Router.push('/pageA')}}>去A页面</button>
    
    复制代码
    

    参数传递与接收

    Next.js中只能通过通过query(?id=1)来传递参数,而不能通过(path:id)的形式传递参数。

    import Link from 'next/link'
    
    //传递
    <Link href="/blogDetail?bid=23"><a>{blog.title}</a></Link>
    
        
        
    //blog.js
    import { withRouter} from 'next/router'
    import Link from 'next/link'
    
    const BlogDetail = ({router})=>{
        return (
            <>
                <div>blog id: {router.query.name}</div>
                <Link href="/"><a>返回首页</a></Link>
            </>
        )
    }
    //withRouter是Next.js框架的高级组件,用来处理路由用的
    export default withRouter(BlogDetail)
    
    
    /************************************************************************************/
    import Router from 'next/router'
    
    <button onClick={gotoBlogDetail} >博客详情</button>
    
    function gotoBlogDetail(){
        Router.push('/blogDetail?bid=23')
    }
    
    //object 形式
    function gotoBlogDetail(){
        Router.push({
            pathname:"/blogDetail",
            query:{
                bid:23
            }
        })
    }
    
    <Link href={{pathname:'/blogDetail',query:{bid:23}}><a>博客详情</a></Link>
    
    复制代码
    

    动态路由

    pages/post/[pid].js
    route : /post/abc  -->  query : { "pid": "abc" }
    
    
    pages/post/[pid]/[comment].js
    route : /post/abc/a-comment  -->  query : { "pid": "abc", "comment": "a-comment" }
    
    
    复制代码
    

    钩子事件

    利用钩子事件是可以作很多事情的,比如转换时的加载动画,关掉页面的一些资源计数器.....

    //路由发生变化时
    Router.events.on('routeChangeStart',(...args)=>{
        console.log('1.routeChangeStart->路由开始变化,参数为:',...args)
    })
    
    //路由结束变化时
    Router.events.on('routeChangeComplete',(...args)=>{
        console.log('routeChangeComplete->路由结束变化,参数为:',...args)
    })
    
    //浏览器 history触发前
    Router.events.on('beforeHistoryChange',(...args)=>{
        console.log('3,beforeHistoryChange->在改变浏览器 history之前触发,参数为:',...args)
    })
    
    //路由跳转发生错误时
    Router.events.on('routeChangeError',(...args)=>{
        console.log('4,routeChangeError->跳转发生错误,参数为:',...args)
    })
    
    /****************************hash路由***********************************/
    
    Router.events.on('hashChangeStart',(...args)=>{
        console.log('5,hashChangeStart->hash跳转开始时执行,参数为:',...args)
    })
    
    Router.events.on('hashChangeComplete',(...args)=>{
        console.log('6,hashChangeComplete->hash跳转完成时,参数为:',...args)
    })
    复制代码
    

    获取数据

    getStaticProps

    构建时请求数据

    在build阶段将页面构建成静态的html文件,这样线上直接访问HTML文件,性能极高。

    • 使用getStaticProps方法在build阶段返回页面所需的数据。
    • 如果是动态路由的页面,使用getStaticPaths方法来返回所有的路由参数,以及是否需要回落机制。
    // posts will be populated at build time by getStaticProps()
    function Blog({ posts }) {
      return (
        <ul>
          {posts.map((post) => (
            <li>{post.title}</li>
          ))}
        </ul>
      )
    }
    
    // This function gets called at build time on server-side.
    // It won't be called on client-side, so you can even do
    // direct database queries. See the "Technical details" section.
    export async function getStaticProps(context) {
      // Call an external API endpoint to get posts.
      // You can use any data fetching library
      const res = await fetch('https://.../posts')
      const posts = await res.json()
    
      // By returning { props: { posts } }, the Blog component
      // will receive `posts` as a prop at build time
      return {
        props: {
          posts,
        },
      }
    }
    
    export default Blog
    复制代码
    

    getServerSideProps

    每次访问时请求数据

    页面中export一个asyncgetServerSideProps方法,next就会在每次请求时候在服务端调用这个方法。

    • 方法只会在服务端运行,每次请求都运行一边getServerSideProps方法
    • 如果页面通过浏览器端Link组件导航而来,Next会向服务端发一个请求,然后在服务端运行getServerSideProps方法,然后返回JSON到浏览器。
    function Page({ data }) {
      // Render data...
    }
    
    // This gets called on every request
    export async function getServerSideProps(context) {
      // Fetch data from external API
      const res = await fetch(`https://.../data`)
      const data = await res.json()
    
      // Pass data to the page via props
      return { props: { data } }
    }
    
    export default Page
    复制代码
    

    CSS支持

    添加全局样式表

    要将样式表添加到您的应用程序中,请在 pages/_app.js 文件中导入(import)CSS 文件。

    在生产环境中,所有 CSS 文件将自动合并为一个经过精简的 .css 文件。

    你应该 只在 pages/_app.js 文件中导入(import)样式表

    从 Next.js 9.5.4 版本开始,你可以在应用程序中的任何位置从 node_modules 目录导入(import) CSS 文件了。

    对于导入第三方组件所需的 CSS,可以在组件中进行。

    添加组件级CSS

    • [name].module.css

      //login.module.css
      .loginDiv{
          color: red;
      }
      
      //修改第三方样式
      .loginDiv :global(.active){
          color:rgb(30, 144, 255) !important;
      }
      复制代码
      
      import styles from './login.module.css'
      
      <div className={styles.loginDiv}/>
      
      复制代码
      

      Next.js 允许你导入(import)具有 .scss.sass 扩展名的 Sass 文件。 你可以通过 CSS 模块以及 .module.scss.module.sass 扩展名来使用组件及的 Sass

      npm i sass --save

      如果要配置 Sass 编译器,可以使用 next.config.js 文件中的 sassOptions 参数进行配置。

      const path = require('path')
      
      module.exports = {
        sassOptions: {
          includePaths: [path.join(__dirname, 'styles')],
        },
      }
      复制代码
      
    • CSS-in-JS

      可以使用任何现有的 CSS-in-JS 解决方案。 最简单的一种是内联样式:

      <p style={{ color: 'red' }}>hi there</p>
      复制代码
      

      使用 styled-jsx 的组件就像这样

      function HelloWorld() {
        return (
          <div>
            Hello world
            <p>scoped!</p>
            <style jsx>{`
              p {
                color: blue;
              }
              div {
                background: red;
              }
              @media (max-width: 600px) {
                div {
                  background: blue;
                }
              }
            `}</style>
            <style global jsx>{`
              body {
                background: black;
              }
            `}</style>
          </div>
        )
      }
      
      export default HelloWorld
      复制代码
      

    自定义Header

    <Head>
        <title>我是最胖的!</title>
        <meta charSet='utf-8' />
    </Head>
    

    相关文章

      网友评论

          本文标题:NextJS入门之探索篇

          本文链接:https://www.haomeiwen.com/subject/vzbwddtx.html