新版 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

运行打包好的文件

npm run start

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/66240.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

iOS - 资源按需加载 - ODR

一、瘦身技术大图 二、On-Demand Resources 简介 将其保存管理在苹果的服务器&#xff0c;按需使用资源、优化包体积&#xff0c;实现更小的应用程序。ODR 的好处&#xff1a; 应用体积更小&#xff0c;下载更快&#xff0c;提升初次启动速度资源会在后台下载操作系统将会在磁…

openGauss学习笔记-59 openGauss 数据库管理-相关概念介绍

文章目录 openGauss学习笔记-59 openGauss 数据库管理-相关概念介绍59.1 数据库59.2 表空间59.3 模式59.4 用户和角色59.5 事务管理 openGauss学习笔记-59 openGauss 数据库管理-相关概念介绍 59.1 数据库 数据库用于管理各类数据对象&#xff0c;与其他数据库隔离。创建数据…

【数据结构】树和二叉树的概念及结构(一)

目录 一&#xff0c;树的概念及结构 1&#xff0c;树的定义 2&#xff0c;树结点的分类及关系 3&#xff0c;树的表示 二&#xff0c;二叉树的概念及结构 1&#xff0c;二叉树的定义 2&#xff0c;特殊的二叉树 3&#xff0c;二叉树的性质 4&#xff0c;二叉树的存储结构 1&…

无涯教程-Android Intent Standard Extra Data函数

下表列出了各种重要的Android Intent Standard Extra Data。您可以查看Android官方文档以获取额外数据的完整列表- Sr.NoExtra Data & Description1 EXTRA_ALARM_COUNT 用作AlarmManager intents(意图)中的int Extra字段,以告诉正在调用的应用程序intents(意图)释放了多少…

Pnpm,npm,yarn

npm 最初的npm只是简单的通过依赖去递归安装包&#xff0c;所以说每个依赖都会有自己的node_modules,node_modules是嵌套的。一个项目会存在多个包&#xff0c;多个包之间难免会有公共的依赖&#xff0c;node_modules嵌套的话&#xff0c;这样公共依赖就会下载多次。会造成磁盘…

Three.js之层级模型

参考资料 Vector3与模型位置、缩放属性…模型隐藏或显示 知识点 注&#xff1a;基于Three.jsv0.155.0 Group&#xff1a;add()遍历模型树结构、查询模型节点&#xff1a;name、traverse、getObjectByName()本地坐标和世界坐标&#xff1a;getWorldPosition()改变模型相对局…

MQTT异常掉线原因

一、业务场景 我们在使用MQTT协议的时候&#xff0c;有些伙伴可能会遇到MQTT客户端频繁掉线、上线问题 二、原因分析及异常处理 1.原因&#xff1a;使用相同的clientID 方案&#xff1a;全局使用的clientID保证唯一性&#xff0c;可以采用UUID等方式 2.原因: 当前用户没有Top…

Shell文件常用语法

参考链接&#xff1a;https://juejin.cn/post/7249347651787980861 Shell脚本是一种命令语言&#xff0c;可以用于自动化执行各种任务。在脚本中&#xff0c;我们可以通过参数来传递信息&#xff0c;这样脚本就可以根据这些信息来执行特定的操作。本文将介绍如何在shell脚本中…

【数据结构】二叉树篇|超清晰图解和详解:二叉树的序列化和反序列化

博主简介&#xff1a;努力学习的22级计算机科学与技术本科生一枚&#x1f338;博主主页&#xff1a; 是瑶瑶子啦每日一言&#x1f33c;: 你不能要求一片海洋&#xff0c;没有风暴&#xff0c;那不是海洋&#xff0c;是泥塘——毕淑敏 目录 一、核心二、题目2.1:前序遍历2.2&…

【博客701】shell实现保留网络现场:ping失败时执行mtr

shell实现保留网络现场&#xff1a;ping失败时执行mtr 场景 当我们网络出现抖动&#xff0c;到某个目的地ping不通时&#xff0c;我们想知道路径上哪里出现问题时可以在那时候执行mtr并保留下现场以供排查 实现&#xff1a;ping_and_mtr.sh #!/bin/bash# 定义要ping的IP地址列…

x86_64 ansible 源码编译安装

源码 GitHub - ansible/ansible: Ansible is a radically simple IT automation platform that makes your applications and systems easier to deploy and maintain. Automate everything from code deployment to network configuration to cloud management, in a languag…

js常用方法总结

1、slice 和 splice slice表示截取&#xff0c;slice(start,end)&#xff0c;不改变原数组&#xff0c;返回新数组。 splice表示删除&#xff0c;splice(start,length,item)&#xff0c;会改变原数组&#xff0c;从某个位置开始删除多个元素&#xff0c;并可以插入新的元素。…

2.4 关系数据库

思维导图&#xff1a; 前言&#xff1a; 这段话描述了“关系数据库”及其背后的理论基础。首先&#xff0c;我们来拆分这段话并逐步解释每部分。 关系数据库是采用关系模型作为数据组织方式的数据库。 这句话的关键是“关系模型”。关系模型是一种表示和操作数据库的理论模型…

操作系统清华同步笔记:定义概述+计算机内存和硬盘布局+启动流程顺序+中断、异常和系统调用

定义概述 从用户角度来看&#xff0c;操作系统是一个控制软件&#xff0c;用以管理应用程序&#xff0c;为应用程序提供服务&#xff0c;杀死应用程序等。从内部文件角度来看&#xff0c;操作系统是一个资源管理器&#xff0c;用以管理外设&#xff0c;分配资源。层次结构&…

命令行编译VS工程

先输入以下命令&#xff0c;因为命令出错了&#xff0c;就会弹出帮助&#xff0c;如下&#xff1a; "C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\devenv.exe" /help 反正就是Microsoft Visual Studio 的安装路径。 帮助界面如下&#xff1a…

Selenium如何用于编写自动化测试脚本?

Selenium如何用于编写自动化测试脚本&#xff1f;它提供了许多测试工具和API&#xff0c;可以与浏览器交互&#xff0c;模拟用户操作&#xff0c;检查网页的各个方面。下面是一些步骤&#xff0c;可以帮助你编写Selenium自动化测试脚本。 1、安装Selenium库和浏览器驱动程序 首…

core dump管理在linux中的前世今生

目录 一、什么是core dump&#xff1f; 二、coredump是怎么来的&#xff1f; 三、怎么限制coredump文件的产生&#xff1f; ulimit 半永久限制 永久限制 四、从源码分析如何对coredump文件的名字和路径管理 命名 管理 一些问题的答案 1、为什么新的ubuntu不能产生c…

java设计模式---策略模式

策略模式的定义 策略设计模式是一种行为设计模式。当在处理一个业务时&#xff0c;有多种处理方式&#xff0c;并且需要再运行时决定使哪一种具体实现时&#xff0c;就会使用策略模式。 策略模式的类图&#xff1a; 策略模式的实现 在支付业务中&#xff0c;有三种付款方式&…

RabbitMQ工作模式-工作队列

官网关于工作模式的解释地址&#xff1a;https://www.rabbitmq.com/getstarted.html Work Queue&#xff08;工作队列&#xff09; 生产者发消息&#xff0c;启动多个消费者来消费消息&#xff0c;每个消费者仅消费部分消息&#xff0c;可达到负载均衡的效果。 创建生产者 i…

使用docker、docker-compose部署微服务

使用docker、docker-compose部署微服务 一、使用docker部署1、准备2、上传jar包3、编写dockerfile文件3、构建镜像和容器 二、使用docker-compose部署1、准备服务的jar包和dockerfile文件2、编写docker-compose.yml文件3、docker-compose常用命令&#xff08;1&#xff09;、前…