Nextjs使用教程

一.手动创建项目

建议看这个中文网站文档,这个里面的案例配置都是手动的,也可以往下看我这个博客一步步操作
1.在目录下执行下面命令,初始化package.json文件

npm init -y

2.安装react相关包以及next包

yarn add next react react-dom
// 或者
npm install --save next react react-dom

3.在package.json文件的script节点,新增以下内容

  "scripts": {...,"dev": "next",  // 开发时运行"build": "next build", // 打包时运行"start": "next start"  // 打完包启动服务的命令}

注意:Next.js 只支持React 16及以上

4.根目录下新建pages目录(这里面就是所有页面代码了,会根据这个目录的内容自动生成路由)

5.在pages里面新建index.js,放入以下内容进行测试

export default function(){return <div>我是pages/index下面的内容</div>
}

6.启动项目测试

npm run dev
// 或者
yarn run dev

7.访问控制台的local地址,显示出如下页面

在这里插入图片描述
8.打包

npm run build
// 或者
yarn run build

打完包会在项目下新建生成一个.next文件,在根目录下执行如下命令会和开发时看到的效果一致

npm run start
// 或者
yarn run start

二.快速创建项目

官网文档

执行下面创建项目的命令

npx create-next-app next-create

下面会出现一堆询问的配置信息,这里直接走默认就好了

定义路由

这里的页面都是统一放到app文件夹下面每个文件的page.js文件

例如直接访问localhost:3000则访问的是app/page.js文件

例如直接访问localhost:3000/user则访问的是app/user/page.js文件

export default function(){// className={"text-red-500"} 使用原子化css标签return <div className={"text-red-500"}>我是user/page文件</div>
}

如果访问的页面有很多网格效果,则去app/globals.css里面把样式都删除,只留前三行即可

页面与布局

将app/Layout.js进行改造

import { Inter } from "next/font/google";
import "./globals.css";const inter = Inter({ subsets: ["latin"] });export const metadata = {title: "Create Next App",  // 网站标题description: "Generated by create next app", // 描述信息
};export default function RootLayout({ children }) {return (<html lang="en"><body className={inter.className}>app下面的layout{children}</body></html>);
}

新建app/user/Layout.js存入以下内容

export default function userLayout({ children }) {return (<section>user下面的layout{children}</section>);
}

访问localhost:3000

在这里插入图片描述
访问localhost:3000/user

在这里插入图片描述
通过对比可以发现,app下面的就是公共的根样式,下面每个Layout.js都会继承到,然后每个文件夹下都可以定义当前路由页面的样式

链接和导航

修改下app/page.js内容如下

'use client';
import Link from "next/link";
import { useRouter } from "next/navigation";export default function Home() {const router = useRouter()return (<><h1 className="text-4xl text-orange-600">Hello Name</h1><br></br><Link href={"/user"}>跳转到user路由</Link><br></br><button onClick={()=>{router.push('/user')}}>点击跳转/user</button></>);
}

滚动到新路由的指定位置处,相当于锚点链接

<Link href="/dashboard#settings">Settings</Link>// Output
<a href="/dashboard#settings">Settings</a>

路由组

项目下新建三个路径文件

  • app/(marketing)/about/page.js
  • app/(marketing)/bolg/page.js
  • app/(marketing)/(shop)/acconut/page.js

在每个page.js里面随便写点内容,访问以下路径

  • localhost:3000/about
  • localhost:3000/bolg
  • localhost:3000/account

可以发现都能被访问到,总结规律就是文件夹名字带括号的相当于可以忽略了

路由组不参与url的设定的

个人感觉唯一作用是用于设置共同的Layout.js

创建如下两个Layout.js文件

  • app/(marketing)/Layout.js
  • app/(marketing)/(shop)/Layout.js

在这两个里面添加如下代码

export default function userLayout({ children }) {return (<section>marketing下面的layout{children}</section>);
}
export default function userLayout({ children }) {return (<section>marketing下面shop的layout{children}</section>);
}

运行后会发现,marking的Layout,js被它里面所有文件所共用,shop里面的Layout.js被shop里面的文件所共用,因为这个案例shop在marking里面的,因此shop里面的文件也共用marking里面的样式,这就是路由组,按照上面传统的方式建路由,需要每个文件单独设置自己的Layout.js,使用路由组可以达到复用性

动态路由

在app/user新建[username]文件夹,里面的page.js文件内容如下

export default function({params}){console.log('params',params);return <><div>我是user/[username]动态路由{params.username}</div></>
}

将app/page.js内容修改如下

'use client';
import Link from "next/link";
import { useRouter } from "next/navigation";export default function Home() {const router = useRouter()return (<><h1 className="text-4xl text-orange-600">Hello Name</h1><br></br><Link href={"/user/王二"}>跳转到user路由</Link><br></br><button onClick={()=>{router.push('/user/王五')}}>点击跳转/user</button></>);
}

当点击跳转到路由时,后面的参数就是动态参数,文件名username就是参数名,可以被params.username接收到并显示到页面上

上面有个弊端就是只支持一级动态参数,如果希望多级的话可以将[username]文件名换成[…username]这样就是可以匹配到后面所有参数,如下地址

  • localhost:3000/user/1/2/3/4/5

效果图

在这里插入图片描述
但是这里建议将[…username]文件名替换为[[…username]],两者区别在于[[…username]]当动态参数为空时也会被匹配到,剩余部分两者功能一致

Loadding加载和流的处理

1.在app下面新建Loading.js组件

export default function(){return <div className={"text-2xl text-pink-400"}>Loading...</div>
}

2.修改app/Layout.js

import { Inter } from "next/font/google";
import { Suspense } from "react";
import Loading from './loading';  // 引入app/loading.js
import "./globals.css";const inter = Inter({ subsets: ["latin"] });export const metadata = {title: "Create Next App",  // 网站标题description: "Generated by create next app", // 描述信息
};export default function RootLayout({ children }) {return (<html lang="en"><body className={inter.className}><Suspense fallback={<Loading></Loading>}> // 2.使用SusPense将页面包裹app下面的layout{children}</Suspense></body></html>);
}

子组件代码

这里使用了async/await模拟了一下异步,这是个细节,因为上面的loadding效果如果要出来的话,页面数据必须要是有异步效果,因为我没注意到这点,费了点时间才搞明白

export default async function Posts() {await new Promise((resolve) => setTimeout(resolve, 2000));return <div>1111</div>;
}

注意:将Lodding放到app/Layout.js里面包裹的话,则针对所有页面生效,如果某个页面有不一样的loading效果的话,则需要在当前文件夹里面的Layout.js去单独引入对应的Loading.js,可以在当前文件夹里面创建个Loading.js,这样的话Loading.js的样式仅仅作用于当前文件夹下的所有页面

import { Suspense } from "react";
export default function userLayout({ children }) {return (<section>// 这个loading效果仅作用于当前文件夹下面的所有页面<Suspense fallback={<div className={"text-2xl text-pink-400"}>Loading...</div>}>user下面的layout{children}</Suspense></section>);
}

注意:必须是渲染的页面内有异步操作(如async/await)才会有Loading.js效果

错误处理

新建app/error.js,放入以下内容

'use client'export default function({error,reset}){return (<div><h2>我是全局的错误样式处理</h2><button onClick={()=>reset()}>重试一下</button></div>)
}

也可以对每个页面单独定义路由样式,只需要在目标页面的文件夹内新建error.js,放入以下内容即可

例如我在app/user/error.js内加入以下内容

'use client'export default function({error,reset}){return (<div><h2>app/user 页面内有错误啦!!!</h2><button onClick={()=>reset()}>重试一下</button></div>)
}

例如我们在目标的user页面加入一些错误信息

export default function Posts() {console.log('a',a);  // 这里没有a变量,因此这里会报错return <div>1111</div>;
}

当我们在浏览器访问localhost:3000/user就会报出以下错误

在这里插入图片描述
当我们访问其他页面有错误信息时,但是没有给那个页面单独定义错误样式,则会触发全局的错误样式

例如访问: localhost:3000/about

在这里插入图片描述

组件化渲染

并行路线,也就是web端的组件

在app下面新建@home和@setting文件夹,里面都新建一个page.js文件,在里面写一点页面

在app/Layout.js里面改为如下页面代码

import { Inter } from "next/font/google";
import { Suspense } from "react";
import Loading from './loading';
import "./globals.css";const inter = Inter({ subsets: ["latin"] });export const metadata = {title: "Create Next App",  // 网站标题description: "Generated by create next app", // 描述信息
};export default function RootLayout({ children,home,setting }) {return (<html lang="en"><body className={inter.className}><Suspense fallback={<Loading></Loading>}>app下面的layout{home}{children}{setting}</Suspense></body></html>);
}

在这里插入图片描述

可以发现组件效果已经出来了

但是上面的仅限于在Layout.js里面使用的组件,下面是可以应用到我们页面里面的组件的案例

在app平级处创建components/frame/index.js,放入以下内容

import Image from "next/image";export default function({photo}){console.log('photo',photo);return <><Image src={photo.src} alt="" width={600} height={600} className={'w-full object-cover aspect-square col-span-2 w-28'}></Image></>
}

在app里面新建photo/page.js文件,插入以下内容

import Photo from "@/components/frame"  // 引入组件
export default function(){const photo = {src:'https://take-saas.oss-cn-hangzhou.aliyuncs.com/wechat_applets/coach/bgcimg/bgc-13.png'}// 给组件传值return <Photo photo={photo}></Photo>
}

注意:这里可能会报错图片问题(网络图片需要加一下白名单才能正常加载,如下在next.config.mjs里面进行配置)

/** @type {import('next').NextConfig} */
const nextConfig = {images:{domains:['take-saas.oss-cn-hangzhou.aliyuncs.com'] // 这里是存放域名白名单处}
};export default nextConfig;

然后就可以看到图片正常加载了

在这里插入图片描述

定义404页面

在app下面新建not-found.js,放入以下内容

export default function(){return <div className={"text-2xl text-pink-400"}>访问页面不存在...</div>
}

当页面访问一个不存在的页面路由时,页面显示效果如下

在这里插入图片描述
PS:由于博客内容都是自学做的整理,在某一次排查问题时,也就是刚好博客写到这里时,刷到了一个博主的nextjs教程合集,也挺详细的,力推点击进入合集地址

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

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

相关文章

使用Python操作Redis

大家好&#xff0c;在当今的互联网时代&#xff0c;随着数据量和用户量的爆发式增长&#xff0c;对于数据存储和处理的需求也日益增加。Redis作为一种高性能的键值存储数据库&#xff0c;以其快速的读写速度、丰富的数据结构支持和灵活的应用场景而备受青睐。本文将介绍Redis数…

猫头虎分享已解决Bug || Error: ‘fetch‘ is not defined

原创作者&#xff1a; 猫头虎 作者微信号&#xff1a; Libin9iOak 作者公众号&#xff1a; 猫头虎技术团队 更新日期&#xff1a; 2024年6月6日 博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &…

独立游戏之路 -- 上架TapTap步骤和注意事项

个人开发者游戏上架TapTap上架步骤和注意事项 一、TapTap 介绍二、独立游戏上架 TapTap 的步骤2.1 创建游戏2.2 提交游戏审核2.3 TapTap 平台上发布。 三、注意事项3.1 关于备案3.2 遵守 TapTap 的规定3.3 保证游戏质量 四、常见问题4.1 隐私政策问题4.2 先发布还是先优化&…

PIVOT函数-动态列

一、需求说明 原始表&#xff1a; select * from pathogen_pro; 将pm_name的值转成对应的列&#xff0c;效果如下 二、PIVOT函数说明 PIVOT(<聚合函数>([聚合列值]) FOR [行转列前的列名] IN([行转列后的列名1],[行转列后的列名2],[行转列后的列名3],.......[行转列后…

Julia编程11:变量作用域 Scope of Variables

There are two main types of scopes in Julia, global* scope* and local* scope*. Julia有全局变量作用域和局部变量作用域&#xff0c;函数或者一些结构体、循环体如for等是否内部是局部环境可以参照下表。 ConstructScope typeAllowed withinmodule, baremoduleglobalglo…

.Net 基于.Net8开发的一个Asp.Net Core Webapi后端框架

1.项目结构 该项目是基于.net8开发的Asp.Net Core WebApi后端服务,集成了Efcore,Autofac,Jwt,AutoMapper,Serilog,Quartz,MiniExcel等组件。该框架简单易上手&#xff0c;没有额外的学习成本; 该项目采用了多层结构设计&#xff0c;有利于解耦&#xff0c;包含公共层&#xff0…

MySQL数据库整体知识点简述

目录 第一章&#xff1a;数据库系统概述 第二章&#xff1a;信息与数据模型 第3章 关系模型与关系规范化理论 第四章——数据库设计方法 第六-七章——MySQL存储引擎与数据库操作管理 第九章——索引 第10章——视图 第11章——MySQL存储过程与函数 第12章——MySQL 触…

IIS7整合Tomcat9服务器,并搭建ASP+PHP+JSP完整运行环境

本文以Windows Vista系统为例&#xff0c;详细讲解IIS7整合Tomcat服务器&#xff0c;同时支持ASPPHPJSP三种Web动态网页技术的方法。 Vista系统自带的IIS版本为7.0&#xff0c;能安装的IE浏览器的最高版本为IE9。IE9也是Vue2前端框架支持的最低浏览器版本。 【准备工作】 去微…

蓝桥杯物联网竞赛_STM32L071_20_用printf将数据显示在OLED上

需求&#xff1a; 第十五届国赛确实有点变态&#xff0c;显示部分大概有6个所以需要大量将sprintf与OLED_ShowString配合使用才能显示相应格式的数据&#xff0c;所以我在想能不能简化一下这一部分直接用写好的printf语句将数据显示到显示屏上呢&#xff1f; 代码&#xff1a…

树--搜索二叉树

现有一棵结点数目为n的二叉树&#xff0c;采用二叉链表的形式存储。对于每个结点均有指向左右孩子的两个指针域&#xff0c;而结点为n的二叉树一共有n-1条有效分支路径。那么&#xff0c;则二叉链表中存在2n-(n-1)n1个空指针域。那么&#xff0c;这些空指针造成了空间浪费。 例…

【TB作品】msp430g2553单片机,秒表,LCD1602,Proteus仿真

功能 秒表 动图&#xff1a; 部分代码 这段代码是用C语言编写的&#xff0c;用于在基于德州仪器MSP430微控制器的平台上实现一个简易的电子秒表功能。 #include <msp430.h> #include "LCD.h"unsigned int second 0; unsigned int millisecond10…

【HarmonyOS】应用振动效果实现

一、问题背景&#xff1a; 应用在强提醒场景下&#xff0c;一般会有马达振动的效果&#xff0c;提示用户注意力的关注。 比如消息提醒&#xff0c;扫码提示&#xff0c;删除键确认提示等。 针对高定制化或者固定的振动方式&#xff0c;我们需要有不同的方案实现&#xff0c;马…

php项目加密源码

软件简介 压缩包里有多少个php就会被加密多少个PHP、php无需安装任何插件。源码全开源 如果上传的压缩包里有子文件夹&#xff08;子文件夹里的php文件也会被加密&#xff09;&#xff0c;加密后的压缩包需要先修复一下&#xff0c;步骤&#xff1a;打开压缩包 》 工具 》 修…

【云原生】Kubernetes----Ingress对外服务

目录 引言 一、K8S对外方式 &#xff08;一&#xff09;NodePort 1.作用 2.弊端 3.示例 &#xff08;二&#xff09;externalIPs 1.作用 2.弊端 3.示例 &#xff08;三&#xff09;LoadBalancer 1.作用 2.弊端 &#xff08;四&#xff09;Ingress 二、Ingress的…

gitea的git库备份与恢复

文章目录 gitea库的备份与恢复概述笔记实验环境更新git for windows更新 TortoiseGit备份已经存在的gitea的git库目录使用gitea本身来备份所有git库目录将gitea库恢复到新目录m1m2m3启动gitea - 此时已经恢复完成FETCH_HEAD 中有硬写位置再查一下app.ini, 是否改漏了。m1m2 总结…

容器中运行ip addr提示bash: ip: command not found【笔记】

容器中运行ip addr提示bash: ip: command not found 原因没有安装ip命令。 rootdocker-desktop:/# ip addr bash: ip: command not found rootdocker-desktop:/# apt-get install -y iproute2

谷歌广告怎么开户?Google推广开户费用、代运营流程、代理开户、投放价格

谷歌推广&#xff08;Google Ads广告&#xff09;是指Google公司面向全球用户&#xff0c;在其自有搜索引擎、YouTube视频、Gmail邮箱等各类自有产品提供的广告位中&#xff0c;展示的各类互联网广告。谷歌广告&#xff0c;有很多种衍生的叫法&#xff1a;谷歌SEM、谷歌竞价、谷…

cron表达式的讲解及其在若依定时任务中的使用

目录 前言介绍一 cron的结构二 各域的含义三 常用cron表达式 实例1 后台添加定时任务处理类2 前端新建定时任务信息3 点击执行一次4 启动定时任务 前言 在实际项目开发中Web应用有一类不可缺少的&#xff0c;那就是定时任务。 定时任务的场景可以说非常广泛&#xff0c;比如某…

Day42 代码随想录打卡|二叉树篇---二叉树的所有路径

题目&#xff08;leecode T257&#xff09;&#xff1a; 给你一个二叉树的根节点 root &#xff0c;按 任意顺序 &#xff0c;返回所有从根节点到叶子节点的路径。 叶子节点 是指没有子节点的节点。 方法&#xff1a;本题需要对二叉树中的所有路径进行遍历&#xff0c;并且是…

vue-router 源码分析——2. router-link 组件是如何实现导航的

这是对vue-router 3 版本的源码分析。 本次分析会按以下方法进行&#xff1a; 按官网的使用文档顺序&#xff0c;围绕着某一功能点进行分析。这样不仅能学习优秀的项目源码&#xff0c;更能加深对项目的某个功能是如何实现的理解。这个对自己的技能提升&#xff0c;甚至面试时…