新版 Next.js 从入门到入土

这篇具有很好参考价值的文章主要介绍了新版 Next.js 从入门到入土。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本教程用的Next.js 是 13 版本

Next.js 简介

  1. 完善的React项目,搭建轻松
  2. 自带数据同步,解决服务端渲染最大难点
  3. 丰富的插件
  4. 灵活配置

创建第一个项目

手动创建

初始化
npm init
安装所需要的依赖包
npm install --save react react-don next
增加快捷命令
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "next",
    "build": "next build",
    "start": "next start"
  },
创建测试文件

在根目录下创建pages文件夹,并在该文件下创建 index.js

pages 文件夹是Next 规定的,在这个文件夹下写入的文件,Next.js 会自动创建对应的路由

function Index() {
    return (
        <div>Halo Next.js</div>
    )
}

export default Index

运行 npm run dev

creact-next-app 脚手架创建Next.js 项目

创建项目
npx create-next-app@latest

第一次创建项目,若没有安装nextjs 会提示是否安装

What is your project named? my-app                              // 项目名
Would you like to use TypeScript? No / Yes                      // TypeScript 
Would you like to use ESLint? No / Yes                          // ESLint
Would you like to use Tailwind CSS? No / Yes                    // Tailwind CSS
Would you like to use `src/` directory? No / Yes                // src 作为根目录
Would you like to use App Router? (recommended) No / Yes        // 路由
Would you like to customize the default import alias? No / Yes  // 自定义默认导入别名
What import alias would you like configured? @/*                // 配置什么导入别名

运行 npm run dev

Next.js 的page和component

创建一个新的页面

在page目录下创建 about.js

function About () {
    return (
        <div>About nextjs</div>
    )
}

export default About

访问 http://localhost:3000/about

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

创建二级目录页面

在page目录下创建 home 文件 并在该文件下创建 home.js

function Home () {
    return (
        <div>home nextjs</div>
    )
}

export default Home

访问 http://localhost:3000/home/home

Component组件的制作

创建组件

在src目录下创建 components 目录,并在该目录下创建 buttonComponent.js 文件

export default ({children})=><button>{children}</button>
引用

在home.js 引入

import dynamic from 'next/dynamic'

const ButtonComponent = dynamic(
    () => import('@/components/buttonComponent'),
// { ssr: false }  // 是否关闭 ssr(服务端渲染) 默认是开启
)
使用
<ButtonComponent>按钮</ButtonComponent>

路由

标签式跳转

在home页面新增两个页面

homeA.js

import React from "react";
import Link from "next/link";

const HomeA = () => {
    return (
        <>
            <div>我是HomeA 页面</div>
            <div><Link href="/home/home"><div>去Home页面</div></Link></div>
        </>
    )
}

export default HomeA

homeB.js

import React from "react";
import Link from "next/link";

const HomeB = () => {
    return (
        <>
            <div>我是HomeB 页面</div>
            <div><Link href="/home/home"><div>去Home页面</div></Link></div>
        </>
    )
}

export default HomeB

修改home页面内容

import React from "react"
import Link from "next/link"

function Home () {
    return (
        <div>
            <div>home nextjs</div>
            <div><Link href="/home/homeA"><div>去homeA页面</div></Link></div>
            <div><Link href="/home/homeB"><div>去homeB页面</div></Link></div>
        </div>
    )
}

export default Home

早期版本 Link标签下是要接上a标签的,当前版本(13.4.19)如果加上a标签会报错

Router模块进行跳转(编程式跳转)

修改home.js页面

import React from "react"
import Router from "next/router"

const goHomeA = () => {
    Router.push('/home/homeA')
}

const goHomeB = () => {
    Router.push('/home/homeB')
}

function Home () {
    return (
        <div>
            <div>home nextjs</div>
            <div onClick={goHomeA}>去homeA页面</div>
            <div onClick={goHomeB}>去homeB页面</div>
        </div>
    )
}

export default Home

传参与接收

Next.js 只能通过 query 来传递参数

标签式

修改home.js页面

import React from "react"
import Link from "next/link"

function Home () {
    return (
        <div>
            <div>home nextjs</div>
            <div><Link href="/home/homeA?name=张三&age=18"><div>张三</div></Link></div>
            <div><Link href="/home/homeA?name=李四&age=20"><div>李四</div></Link></div>
        </div>
    )
}

export default Home

修改homeA.js页面

withRouter 是 Next.js 框架的高级组件,用来处理路由用的

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

function Home () {
    return (
        <div>
            <div>home nextjs</div>
            <div><Link href="/home/homeA?name=张三&age=18"><div>写法一</div></Link></div>
            <div><Link href={{
                pathname: '/home/homeA',
                query: {
                    name: '李四',
                    age: 20
                }
            }}><div>写法二</div></Link></div>
        </div>
    )
}

export default withRouter(HomeA)
编程式
import React from "react"
import Router from "next/router"

const goHomeA = () => {
    Router.push('/home/homeA?name=张三&age=18')
}

const goHomeA2 = () => {
    Router.push({
        pathname: '/home/homeA',
        query: {
            name: '李四',
            age: 20
        }
    })
}

function Home () {
    return (
        <div>
            <div>home nextjs</div>
            <div onClick={goHomeA}>写法一</div>
            <div onClick={goHomeA2}>写法二</div>
        </div>
    )
}

export default Home

钩子函数

History
import React from "react"
import Router from "next/router"

Router.events.on('routeChangeStart', (...args) => {
    console.log('routeChangeStart -> 路由开始变化', ...args)
})

Router.events.on('routeChangeComplete', (...args) => {
    console.log('routeChangeComplete -> 路由结束变化', ...args)
})

Router.events.on("beforeHistoryChange", (...args) => {
    console.log('beforeHistoryChange -> 在改变浏览器 history 之前触发', ...args)
})

Router.events.on('routeChangeError', (...args) => {
    console.log('routeChangeError -> 跳转发生错误', ...args)
})

const goHomeA = () => {
    Router.push('/home/homeA?name=张三&age=18')
}

const goHomeA2 = () => {
    Router.push({
        pathname: '/home/homeA',
        query: {
            name: '李四',
            age: 20
        }
    })
}

function Home () {
    return (
        <div>
            <div>home nextjs</div>
            <div onClick={goHomeA}>写法一</div>
            <div onClick={goHomeA2}>写法二</div>
        </div>
    )
}

export default Home
Hash
Router.events.on('hashChangeStart', (...args) => {
    console.log('hashChangeStart -> 路由开始变化', ...args)
})

Router.events.on('hashChangeComplete', (...args) => {
    console.log('hashChangeComplete -> 路由结束变化', ...args)
})

在getInitialProps中获取远端数据

getInitialProps 是挂在 React 组件上的静态方法

如果你使用的是 Next.js 9.3 或更高版本,我们建议你使用 getStaticPropsgetServerSideProps 来替代 getInitialProps

官方推荐的是fetch

fetch 请求

在page目录新建一个request.js 页面

import { withRouter } from "next/router";

function Request ({router, data}) {
    return (
        <>
            <div>{router.name}</div>
            <div>请求页面 {data} </div>
        </>
    )
}

Request.getInitialProps = async () => {
    const res = await fetch('https://api.github.com/repos/vercel/next.js')
    const json = await res.json()
    console.log(json)
    return { stars: json.stargazers_count }
}


export default withRouter(Request)

index.js

import Router from "next/router"

const goRequest = () => {
  Router.push({
    pathname: '/request',
    query: {
        name: '李四',
        age: 20
    }
  })  
}

export default function Home() {
  return (
    <>
      <div>首页</div>
      <div onClick={goRequest}>去Request页面</div>
    </>
  )
}

运行页面,可以发现,getInitialProps 会在服务端渲染时执行,也会在客户端渲染时执行

  1. 当页面通过页面刷新等直接形式访问时,会触发 Nextjs 使用服务端渲染的方式返回页面数据

此时 getInitialProps 会在服务端执行,浏览器端不会执行

  1. 当页面通过浏览器端路由跳转的形式访问时(如浏览器前进后退),该页面渲染不会触发 Nextjs 服务端渲染

所以实际上 getInitialProps 方法会根据当前页面渲染时的端侧不同,自主地选择在 Node 端还是 Client 端执行

getStaticProps

getStaticProps 会在每次页面访问时被请求

修改request.js

import { withRouter } from "next/router";

function Request ({router, content}) {
    return (
        <>
            <div>{router.name}</div>
            <div>请求页面 {content} </div>
        </>
    )
}

export const getStaticProps = async () => {
    const res = await fetch('https://api.github.com/repos/vercel/next.js')
    const json = await res.json()
    console.log(json)
    return {
        props: {
            content: json.stargazers_count
        }
    };
};

export default withRouter(Request)

getStaticProps是用于在构建时预先执行getInitialProps进行的处理并预先生成静态文件的API。 不会在客户端上运行。 始终在服务器端运行。

getServerSideProps

import { withRouter } from "next/router";

function Request ({router, content}) {
    return (
        <>
            <div>{router.name}</div>
            <div>请求页面 {content} </div>
        </>
    )
}

export const getServerSideProps = async context => {
    const res = await fetch('https://api.github.com/repos/vercel/next.js')

    // if (!res) {
        // notFound 强制页面跳转到 404
        // return {
        //     notFound: true
        // };

        // redirect 来将页面重定向
        // return {
        //     redirect: {
        //         destination: '/',
        //         permanent: false
        //     }
        // };
    // }

    const json = await res.json()
    console.log(json)
    return {
        props: {
            content: json.stargazers_count
        }
    };
}


export default withRouter(Request)

通过 next.jsgetServerSideProps,我们在开发中可以很好的协调前后端数据,一些页面初始化数据、页面鉴权可以直接在 getServerSideProps 中进行处理,这样可以大大简化页面逻辑,还保障前后端的统一性。

JSX 编写页面的CSS样式

基础写法

新建style.js 页面

const Style = () => {
    return (
        <>
            <div>style 页面</div>
            <div className="base">基础</div>

            <style jsx>
                {`
                    .base {
                        color: blue;
                        font-size: 16px;
                        margin: 40px;
                        display: block;
                    }
                `}
            </style>
        </>
    )
}

export default Style

要注意,style 后面要jsx next.js 会自动加入一个随机类名,这样就防止CSS的全局污染,如上述代码 base 会变成 base-xxxxxx

动态样式

修改style.js 页面

import React, {useState} from "react"

const Style = () => {

    const [color, setColor] = useState('blue')
    const [fontSize, setFontSize] = useState('16')
    const [margin, setMargin] = useState('40')

    const changeColor = () => {
        setColor(color === 'blue' ? 'red': 'blue')
    }

    const changeFontSize = () => {
        setFontSize(fontSize === '16' ? '20': '16')
    }

    const changeMargin = () => {
        setMargin(margin  === '10' ? '40': '10')
    }


    return (
        <>
            <div>style 页面</div>
            <div className="base">基础</div>

            <button onClick={changeColor}>改颜色</button>
            <button onClick={changeFontSize}>改字体大小</button>
            <button onClick={changeMargin}>改边距</button>

            <style jsx>
                {`
                    .base {
                        color: ${color};
                        font-size: ${fontSize}px;
                        margin: ${margin}px;
                        display: block;
                    }
                `}
            </style>
        </>
    )
}

export default Style

模块懒加载

新建 import.js 页面

引入 dayjs 库

npm i dayjs

如果我们在页面直接引入,那它就会以公共库的形式进行打包发布,就算项目第一个页面不使用moment也会进行加载,这就是资源浪费

懒加载引入的第三方库

import.js

import React,{useState} from "react";

const Import = () => {
    const [time, setTime] = useState()

    const changeTime = async () => {
        const dayjs = await import('dayjs')        
        setTime(dayjs.default(Date.now()).format('YYYY-MM-DD HH:mm:ss'))
    }

    return (
        <>
            <div>import 页面</div>
            <div>当前时间为:{time}</div>
            <button onClick={changeTime}>获取当前时间</button>
        </>
    )
}

export default Import

可以看到我们是在需要的地方才引入

要注意 使用 default 才能生效

懒加载组件

利用 dynamic 引入组件实现

import dynamic from 'next/dynamic'

const ButtonComponent = dynamic(() => import('@/components/buttonComponent'))

const Import = () => {
    return (
        <>
            <div>import 页面</div>
            <ButtonComponent>按钮</ButtonComponent>
        </>
    )
}

export default Import

自定义组件是懒加载的,只有在jsx里用到<ButtonComponent/>时,才会被加载进来,如果不使用就不会被加载

head 组件

那为了更好的进行SEO优化,可以自己定制<Head>标签

创建header.js页面

Next.js已经把<Head>封装好了,本身就是一个组件,可以直接

import Head from 'next/head'

const Header = ()=>{
    return (
        <>
            <Head>
                <title> 头部 </title>   
            </Head>
        </>
    )
}

export default Header

Next.js框架下使用Ant Design UI

Ant Design是一款阿里开源的前端组件库

从React的角度来讲,它就是一个组件库,里边封装了开发中最常用的一些组件,让我们可以通过简单的配置就可以使用他们

让Next.js 支持引入CSS文件

首先创建一个 pages/_app.js(如果不存在的话)。 然后import 该 styles.css 文件。

样式表的全局特性

旧版本可以通过 @zeit/next-sass 支持css,这个在新版本中已移除

Next.js 通过 [name].module.css 文件命名约定来支持 CSS 模块

CSS 模块通过自动创建唯一的类名从而将 CSS 限定在局部范围内。 这使您可以在不同文件中使用相同的 CSS 类名,而不必担心冲突。

此行为使 CSS 模块成为包含组件级 CSS 的理想方法。 CSS 模块文件 可以导入(import)到应用程序中的任何位置

不加module next.js框架会误以为是全局样式,会引发冲突报错

import styles from '@/styles/test.module.css'

const Ant = () => {
    return (
        <>
            <div>Ant 页面</div>
            <p className={styles.default}>测试</p>
        </>
    )
}

export default Ant

支持scss

安装scss

npm install sass

用法与 css一致

import styles from '@/styles/test.module.scss'

const Ant = () => {
    return (
        <>
            <div>Ant 页面</div>
            <p className={styles.default}>测试</p>
        </>
    )
}

export default Ant

安装 ant

npm install antd --save

引入 ant 并使用

新建react.js 页面

import React from 'react';
import { DatePicker } from 'antd';

const App = () => {
  return <DatePicker />;
};

export default App;

babel

为了不让webpack 把整个Ant Design的包都进行打包到生产环境

我们需要你用到 babel

npm install --save babel-plugin-import

在项目根目录建立.babelrc文件

{
    "presets":["next/babel"],  //Next.js的总配置文件,相当于继承了它本身的所有配置
    "plugins":[     //增加新的插件,这个插件就是让antd可以按需引入,包括CSS
        [
            "import",
            {
                "libraryName":"antd"
            }
        ]
    ]
}

这样我们使用那个组件就打包那个组件,同样CSS也是按需打包的

Next.js生产环境打包

配置package.json 文件夹

"start": "next start -p 8088" 

运行打包

npm run build

运行打包好的文件文章来源地址https://www.toymoban.com/news/detail-691875.html

npm run start

到了这里,关于新版 Next.js 从入门到入土的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • next.js报错点

    解决方案 1.大概是引用的组件和本组件重名了,换成其他的就可以 解决方案 我一开始定义的navs是数组类型。 在React中,void[] 是一个数组,它没有元素。由于它没有元素,所以不能将其分配给 ReactNode 类型。 在React中,ReactNode 是所有允许的子节点的类型标签。这两个类型不兼

    2024年02月11日
    浏览(52)
  • 用i18next使你的应用国际化-React

    ref: https://www.i18next.com/ i18next是一个用JavaScript编写的国际化框架。 i18next为您提供了一个完整的解决方案,本地化您的产品从web端到移动端和桌面端。 在react项目中安 i18next 依赖: i18next react-i18next i18next-browser-languagedetector,用于检测用户语言 创建 i18n.js 文件: 在 index.js 中导

    2024年02月15日
    浏览(34)
  • 使用 Flask 部署 Next.js

    原文 使用 Flask 部署 Next.js Flask 和 Next.js 是两个独特的开源 Web 框架,分别构建在 Python 和 JavaScript 编程语言之上。 您可以在没有 Next.js 的情况下构建 Flask 应用程序,也可以在没有 Flask 的情况下构建 Next.js 应用程序。但是,您可能会发现自己使用 Flask 构建了一个应用程序,

    2024年02月12日
    浏览(48)
  • Next.js 学习笔记(六)——缓存

    Next.js 可通过缓存渲染工作和数据请求来提高应用程序的性能并降低成本。本页将深入介绍 Next.js 缓存机制、可用于配置这些机制的 API 以及它们之间的交互方式。 需要知道 :本页将帮助你了解 Next.js 的工作原理,但这并 不是 使用 Next.js 提高工作效率的必要知识。Next.js 的大

    2024年02月01日
    浏览(48)
  • 为什么选择 Next.js 框架?

    Next.js 框架作为一种强大而受欢迎的工具,为开发人员提供了许多优势和便利。本文将探讨 Next.js 框架的优点,并解释为什么选择 Next.js 是一个明智的决策。 文档:https://nextjs.org/docs Next.js 框架提供了先进的服务端渲染(SSR)和静态生成(SSG)能力,使得我们能够在服务器上生

    2024年02月12日
    浏览(51)
  • 5分钟入门 next13

    上半年vercel 推出了 nextjs13 这个大版本,刚好最近有个c端的项目,所以就用了这个框架来写,技术体系基本也是文档提到的 tailwindcss + ts + swr + ssr  ,总的来开发体验还可以,不管是打包速度、文档、错误信息提示目前都还满意,只不过目前nextjs13 中文资料有点少,不过问题

    2024年02月08日
    浏览(40)
  • 使用 Next.js 连接 mysql 数据库

    本文主要为大家介绍,如何使用 Next 框架实现一个简单的 后端接口 ,并且从 数据库 中请求数据返回给前端。 项目创建完成后在 app 文件下新建api文件夹,在 api 文件夹下新建 getData 文件夹,在 getData 文件夹下新建 route.js,这里面用于存储我们的接口信息,如下 注意: 在

    2024年02月22日
    浏览(64)
  • Remix 和 Next.js 中实现依赖注入

    在 Remix 中实现依赖注入需要使用到 context 。下面是一个简单的示例: 首先,在项目根目录下创建 context.js 文件:

    2024年02月10日
    浏览(37)
  • Next.js 13.5 正式发布,速度大幅提升!

    9 月 19 日,Next.js 13.5 正式发布,该版本通过以下方式提高了本地开发性能和可靠性: 本地服务器启动速度提高 22% :使用App和Pages Router可以更快地进行迭代 HMR(快速刷新)速度提高 29% :在保存更改时进行更快的迭代 内存使用量减少 40% :在运行 next start 时测量 优化的包导

    2024年02月08日
    浏览(48)
  • next.js 源码解析 - getStaticProps、getStaticPaths 篇

    😂 好久前写了关于 getStaticProps 和 getStaticPaths 的内容,然而半年过去了源码解析就一直忘记了,不久前有人提醒才想起来,补下坑。 本文主要是解读下 getStaticProps 、 getStaticPaths 相关的源码,不了解这两个 API 的建议先看下之前的文章再看。👀 首先 getStaticProps 是应用于 SS

    2024年02月13日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包