阅读视图

发现新文章,点击刷新页面。

Next.js第二十五章(CSS方案)

Next.js CSS方案

在Next.js可以使用多种Css方案,包括:

  • Tailwind CSS(个人推荐)
  • CSS Modules(创建css模块化,类似于Vue的单文件组件)
  • Next.js内置Sass(css预处理器)
  • 全局Css(全局的css,可以全局使用)
  • Style(内联样式)
  • css-in-js(类似于React的styled-components,不推荐)

Tailwind CSS

Tailwind CSS(css原子化),他是一个css框架,可以让你快速构建网页,他提供了大量的css类,你只需要使用这些类,就可以快速构建网页。

Tailwind CSS

安装教程
npx create-next-app@latest my-project

当我们去创建Next.js项目的时候,选择customize settings(自定义选项) 那么就会出现Tailwind CSS的选项,我们选择Yes即可。

image.png

那么如果我在当时忘记选择Tailwind CSS,我该怎么安装呢?

在 Next.js 中安装并使用 Tailwind CSS

下面是如何在 Next.js 项目中集成 Tailwind CSS 的详细流程:

1. 创建你的 Next.js 项目

如果还没有项目,可以使用 Create Next App 快速初始化:

npx create-next-app@latest my-project --typescript --eslint --app
cd my-project
2. 安装 Tailwind CSS 及相关依赖

通过 npm 安装 tailwindcss@tailwindcss/postcss 以及 postcss 依赖:

npm install tailwindcss @tailwindcss/postcss postcss
3. 配置 PostCSS 插件

在项目根目录下创建 postcss.config.mjs 文件,并添加如下内容:

const config = {
  plugins: {
    "@tailwindcss/postcss": {},
  },
};
export default config;
4. 导入 Tailwind CSS

./app/globals.css 文件中添加 Tailwind CSS 的导入:

@import "tailwindcss";
5. 启动开发服务

运行开发服务:

npm run dev
6. 在项目中开始使用 Tailwind

现在可以直接在组件或页面中使用 Tailwind CSS 的工具类来进行样式编写。例如:

export default function Home() {
  return (
    <h1 className="text-3xl font-bold underline">
      Hello world!
    </h1>
  )
}

这样即可在项目中使用 Tailwind CSS 原子类来快速开发样式。

FAQ

这么多类名我记不住怎么办?

答:你不需要特意去记忆,tailwindCss的类名都是简称,例如backdround-color:red 你可以简写为bg-red-500。另外就是官网也提供文档可以查询,再其次就是还提供了vscode插件,可以自动补全类名。

image.png

CSS Modules

CSS Modules 是一种 CSS 模块化方案,可以让你在组件中使用CSS模块化,类似于Vue的单文件组件(scoped)。

Next.js已经内置了对CSS Modules的支持,你只需要在创建文件的时候新增.module.css后缀即可。例如index.module.css

/** index.module.css */
.container {
  background-color: red;
}
/** index.tsx */
import styles from './index.module.css';
export default function Home() {
  return (
    <div className={styles.container}>
      <h1>Home</h1>
    </div>
  )
}

你会发现他编译出来的类名,就会生成一个唯一的hash值,这样就可以避免类名冲突。

<h1 class="index-module__ifV0vq__test">小满zs Page</h1>

Next.js内置Sass

Next.js已经内置了对Sass的支持,但是依赖还需要手动安装,不过配置项它都内置了,只需要安装一下即可。

npm install --save-dev sass

另外Next.js还支持配置全局sass变量,只需要在next.config.js中配置即可。

import type { NextConfig } from 'next'
const config: NextConfig = {
  reactCompiler: true,
  reactStrictMode: false,
  cacheComponents:false,
  sassOptions:{
    additionalData: `$color: blue;`, // 全局变量
  }
}

export default config

全局Css

全局CSS,就是把所有样式应用到全局路由/组件,那应该怎么搞呢?

在根目录下创建globals.css文件,然后添加全局样式。

/** app/globals.css */
body {
  background-color: red;
}
.flex{
    display: flex;
    justify-content: center;
    align-items: center;
}

layout.tsx文件中引入globals.css文件。

//app/layout.tsx
import './globals.css'
export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}

Style

Style,就是内联样式,就是直接在组件中使用style属性来定义样式。

export default function Home() {
  return (
    <div style={{ backgroundColor: 'red' }}>
      <h1>Home</h1>
    </div>
  )
}

css-in-js

css-in-js,就是把css + js + html混合在一起,拨入styled-components,不推荐很多人接受不了这种写法。

1.安装启用styled-components
npm install styled-components
import type { NextConfig } from 'next'
const config: NextConfig = {
  compiler:{
    styledComponents:true // 启用styled-components
  }
}
export default config
2.创建style-component注册表

使用styled-componentsAPI 创建一个全局注册表组件,用于收集渲染过程中生成的所有 CSS 样式规则,以及一个返回这些规则的函数。最后,使用该useServerInsertedHTML钩子将注册表中收集的样式注入到<head>根布局的 HTML 标签中。

//lib/registry.ts
'use client'
 
import React, { useState } from 'react'
import { useServerInsertedHTML } from 'next/navigation'
import { ServerStyleSheet, StyleSheetManager } from 'styled-components'
 
export default function StyledComponentsRegistry({
  children,
}: {
  children: React.ReactNode
}) {
  // Only create stylesheet once with lazy initial state
  // x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state
  const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet())
 
  useServerInsertedHTML(() => {
    const styles = styledComponentsStyleSheet.getStyleElement()
    styledComponentsStyleSheet.instance.clearTag()
    return <>{styles}</>
  })
 
  if (typeof window !== 'undefined') return <>{children}</>
 
  return (
    <StyleSheetManager sheet={styledComponentsStyleSheet.instance}>
      {children}
    </StyleSheetManager>
  )
}
3.注册style-component注册表
//app/layout.tsx
import StyledComponentsRegistry from './lib/registry'
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html>
      <body>
        <StyledComponentsRegistry>{children}</StyledComponentsRegistry>
      </body>
    </html>
  )
}
4.使用styled-components
'use client';
import styled from 'styled-components';
const StyledButton = styled.button`
  background-color: red;
  color: white;
  padding: 10px 20px;
  border-radius: 5px;
`;
export default function Home() {
  return (
    <StyledButton>Click me</StyledButton>
  )
}

Next.js第二十四章(Prisma)

ORM框架(Object-Relational Mapping)

在传统开发模式中,我们需要把数据存储到数据库,所以需要通过SQL语句来进行操作,例如查询 新增 修改 删除等操作,但是SQL语句太多了,还比较繁琐,所以就有了ORM框架。

ORM框架简单来说就是让我们通过熟悉的语法来操作数据库,我们可以直接使用面向对象的方式来操作数据库,ORM会把我们的操作映射成SQL语句,然后执行。

面向对象查询:

const user = await this.prisma.user.findUnique({
    where: {
        id: 1
    },
    select: {
        id: true,
        name: true,
        email: true
    }
})
console.log(user)

SQL查询:

SELECT id, name, email FROM users WHERE id = 1

Prisma

ORM框架比较多,这里我选择使用Prisma,因为PrismaTypeScript优先的ORM框架,并且支持多种数据库,包括MySQL PostgreSQL SQLite MongoDB等。它以其出色的性能、类型安全性以及与 GraphQL 和 REST API 的集成而闻名

注:我们当前使用的prisma版本是7.3.0为目前最新版(2026-01-29),他每个大版本是有很大差异的,所以建议大家跟我安装一样的版本。

Postgresql

image.png

数据库的种类也是非常多的,这里我选择使用PostgreSQL,完全开源免费,我称为世界第一数据库(个人言论),因为他有非常强大的功能,例如支持高级数据类型,JSON 数组 枚举 布尔值 地理空间GIS,事务与并发能力更强,并且还支持自定义扩展其功能。

PostgresSQL安装教程

  1. 简单粗暴,访问官网www.postgresql.org/download/,选择适合你操作系统的版本,然后下载安装即可。
image.pngimage.pngimage.png
  1. 使用docker安装
docker pull postgres:18
docker run -d --name postgresServer -p 6666:5432 -e POSTGRES_PASSWORD=123456 postgres:18

账号默认为postgres,密码为123456,端口号为6666

安装数据库可视化工具:打开vsCode / Cursor / WebStorm等代码编辑器,安装Database Client插件,然后连接数据库即可。

image.pngimage.png

开始使用Prisma

安装prisma:

npm i prisma -D

安装prisma客户端:

npm install @prisma/client @prisma/adapter-pg pg dotenv

注: prisma7版本需要独立安装适配器

例如postgresql需要安装@prisma/adapter-pgmysql需要安装@prisma/adapter-mariadb

其他数据库请参考www.prisma.io/docs/gettin…

在Next.js项目根目录执行以下命令,初始化prisma:

npx prisma init

执行完成之后他会自动生成prisma文件夹,并且生成schema.prisma文件,以及创建一个env文件和prisma.config.ts文件。

image.png

打开prisma/schema.prisma文件,添加以下内容:

generator client {
  provider = "prisma-client" //使用什么客户端
  output   = "../src/generated/prisma" //生成客户端代码的目录
}

datasource db {
  provider = "postgresql" //连接什么数据库
}

model User {
  id        String   @id @default(cuid()) //主键 
  name      String //用户名
  email     String   @unique //邮箱
  password  String //密码
  createdAt DateTime @default(now()) //创建时间
  updatedAt DateTime @updatedAt //更新时间
  posts     Post[] //关联文章
}

model Post {
  id        String   @id @default(cuid()) //主键
  title     String //标题
  content   String //内容
  createdAt DateTime @default(now()) //创建时间
  updatedAt DateTime @updatedAt //更新时间
  authorId  String //作者ID
  author    User     @relation(fields: [authorId], references: [id],onDelete: Cascade,onUpdate: Cascade) //一对多关联
}
  • @id:主键对应sql语句的PRIMARY KEY
  • @default(cuid()):默认生成一个唯一ID 类似于sql语句的AUTO_INCREMENT
  • @unique:唯一约束对应sql语句的UNIQUE
  • @relation:一对多关联对应sql语句的FOREIGN KEY
  • @relation(fields: [authorId], references: [id],onDelete: Cascade,onUpdate: Cascade):一对多关联对应sql语句的FOREIGN KEY
  • @default(now()):默认生成当前时间 类似于sql语句的CURRENT_TIMESTAMP
  • @updatedAt:更新时间 类似于sql语句的UPDATE CURRENT_TIMESTAMP
  • onDelete: Cascade:级联删除(表示删除主表的时候,从表也删除,非常的方便啊)
  • onUpdate: Cascade:级联更新(表示更新主表的时候,从表也更新,非常的方便啊)

打开.env文件,修改数据库连接信息:

连接规则:DATABASE_URL="postgresql://username:password@localhost:5432/mydb?schema=public"

  • postgresql:数据库类型
  • username:用户名
  • password:密码
  • localhost:主机名
  • 5432:端口号
  • mydb:数据库名
  • schema=public:模式
DATABASE_URL="postgresql://postgres:123456@localhost:6666/test_db"

执行数据库迁移命令:

npx prisma migrate dev --name init

执行完成之后他会在prisma/migrations文件夹中生成一个migration文件,并且生成一个sql文件,然后自动执行sql文件,创建表结构。

image.png

接着执行生成客户端代码命令:

npx prisma generate
#生成路径是 schema.prisma 文件中client output的目录

image.png

编写增删改查

src/lib/prisma.ts

import { PrismaClient } from '../generated/prisma/client' //引入生成客户端代码
import { PrismaPg } from '@prisma/adapter-pg' //引入适配器
const pool = new PrismaPg({ connectionString: process.env.DATABASE_URL }) //创建连接池
const prisma = new PrismaClient({ adapter: pool }) //创建客户端
export default prisma //导出客户端

src/app/api/route.ts

import prisma from "@/lib/prisma"; //@lib是我在tsconfig.json中配置的别名,表示src目录下的lib文件夹
import { NextRequest, NextResponse } from "next/server"; //引入NextRequest, NextResponse

export async function GET(request: NextRequest) {
    const users = await prisma.user.findMany() //查询所有用户
    return NextResponse.json(users) //返回用户列表
}

export async function POST(request: NextRequest) {
    const { name, email, password } = await request.json() //获取请求体
    const user = await prisma.user.create({
        data: { name, email, password } //创建用户
    })
    return NextResponse.json(user) //返回创建的用户
}

export async function PATCH(request: NextRequest) {
    const { id, name, email, password } = await request.json() //获取请求体
    const user = await prisma.user.update({
        where: { id },
        data: { name, email, password } //更新用户
    })
    return NextResponse.json(user) //返回更新后的用户
}

export async function DELETE(request: NextRequest) {
    const { id } = await request.json() //获取请求体
    const user = await prisma.user.delete({
        where: { id } //删除用户
    })
    return NextResponse.json(user) //返回删除后的用户
}

index.http

执行http文件需要在插件市场安装REST Client,然后打开http文件,点击Send Request按钮即可。

image.png

### 创建用户
POST http://localhost:8888/api
Content-Type: application/json

{
    "name": "test",
    "email": "1test@test.com",
    "password": "123456"
}

### 查询所有用户
GET http://localhost:8888/api


### 更新用户
PATCH http://localhost:8888/api
Content-Type: application/json

{
    "id": "cmkyoxflr00004ck82ywc6joi",
    "name": "xiaoman",
    "email": "xiaomansdasdas",
    "password": "dasdasda"
}

### 删除用户
DELETE http://localhost:8888/api
Content-Type: application/json

{
    "id": "cmkyoxflr00004ck82ywc6joi"
}
❌