nextjs项目中,使用postgres的完整案例

目的

通过此案例,可以简单快速的过一下数据库的操作,熟悉app-router这种模式下,client component和server component的两种组件中基本的接口使用。

技术栈

  • nextjs@14.2.* app-router
  • @vercel/postgres@0.10.*
  • typescript@5

重要事情说三遍1

  • app-router!!! 下面所有的代码和目录结构,脱离不开这个模式
  • app-router!!! 下面所有的代码和目录结构,脱离不开这个模式
  • app-router!!! 下面所有的代码和目录结构,脱离不开这个模式

创建表

初始化操作,可以看 最新nextjs中使用postgresSQL 这里

sql语句:CREATE TABLE article (content TEXT);

创建一个存放文章内容的表,字段为content 并且类型为TEXT. 详细的数据类型可以看这里

字符类型描述
character varying(n), varchar(n)变长,有长度限制
character(n), char(n)定长,不足补空白
text变长,无长度限制

创建文章数据(服务端)

sql语句:INSERT INTO article VALUES (${body.content});

接口文件:src/api/add-acticle/route.ts

import { sql } from '@vercel/postgres';
import { NextResponse } from 'next/server';

export async function GET() {
  const { rows } = await sql`SELECT * FROM article`;
  return Response.json({ rows })
}

export async function POST(request: Request) {
    const body = await request.json();
    await sql`INSERT INTO article VALUES (${body.likes});`;
    return NextResponse.json({ status: 200 });
}

创建文章数据(客户端)

目录:src/app/components/create-comp/index.tsx
涉及到react hook使用的组件,必须是use client

  • 以下出现的gyp-gao-ui组件库已发布到npm,如果只是想demo下,自行npm i -S gyp-gao-ui即可,使用中出现问题,可以看 nextjs中集成富文本编辑器wangEditor
  • 或者就是换成随便一个输入框
  • getHostStatic 方法的代码
    在这里插入图片描述
"use client";
import { RichText } from "gyp-gao-ui"; 
import { useState } from "react";
import { getHostStatic } from '../../../utils/static-index';

export default function CreateText() {
  const [data, setData] = useState('');
  const handleInsert = async () => {
    const res = await fetch(
      `${getHostStatic()}/api/add-acticle`,
      {
        method: "post",
        body: JSON.stringify({
          content: data,
        }),
      }
    );
    // 这里res可以自己在服务端那边组装成想要的格式哦
    // 然后前端这边就自行根据不同的结果做一些正常/异常处理
  };

  const handleChange = (value: string) => {
    setData(value);
  }

  return (
    <div>
      <RichText onChange={handleChange} />

      <div className="btn" onClick={handleInsert}>保存数据</div>
    </div>
  );
}

目录:src/app/create/page.tsx
主创建页面,服务端渲染的

import dynamic from 'next/dynamic'
import { Metadata } from 'next';
import './a.scss'; // 天然支持的scss/sass

const RichText = dynamic(() => import("../components/create-comp"), {
  ssr: false,
});

export const metadata: Metadata = {
  title: '创建数据',
}

export default async function CreateText() {

  return (
    <div className='a'>
        <RichText />
    </div>
  );
}

查询展示文章数据 (客户端)

服务端数据生成和渲染

  • getHost 方法代码如下,切记该代码的运行环境不能是use client
    目录:src/utils/index.ts

服务端怎么知道当前项目的域名,通过headers上面的字段查询,官方文档

import { headers } from 'next/headers';

const logPrefix = '[blog-render]:--> '
/** 获取当前域名 */
export const getHost = () => {
    const headersList = headers();
    // https://developer.mozilla.org/docs/Web/API/Headers/get
    // https://nextjs.org/docs/app/api-reference/functions/headers
    const host = headersList.get('host');
    const xForwardedHost = headersList.get('x-forwarded-host');
    const referer = headersList.get('referer');
    const protocol = headersList.get('x-forwarded-proto');
    console.info(logPrefix + 'url:===', host, referer, protocol)
    // 获取协议
    const realProtocol = referer?.split('://')[0] || protocol;
    const realHost = host || xForwardedHost;
    console.info(logPrefix + 'realUrl:==', realProtocol, realHost)
    const url = `${realProtocol}://${realHost}`;
    return url;
}

目录:src/app/components/pre-comp/index.tsx

"use client";
import { RichTextRender } from "gyp-gao-ui";

export default function Preview({ content }: {content: string}) {

  return (
    <div style={{marginBottom: '30px'}}>
      <RichTextRender content={content} />
    </div>
  );
}

目录:src/app/preview/pages.tsx

import { Metadata } from 'next';
import dynamic from 'next/dynamic';
import { getHost } from '../../utils';

export const metadata: Metadata = {
    title: '欢迎预览',
  }

const RichTextReader = dynamic(() => import("../components/pre-comp"), {
    ssr: false,
});

export default async function Preview() {
    const url = getHost();
    const data = await fetch(`${url}/api`);
    const { rows } = await data.json();

    return (
        <div>
            {rows.map((o: { content: string }, i: number) => <RichTextReader key={i} content={o.content} />)}
        </div>
    )
}

效果如下

列表数据展示如下,当然demo就不写那么美观的css了!
在这里插入图片描述

写在最后

找到正确的打开入口,学习就会事半功倍,觉醒吧前端同志。记得给博主点个赞,制作不易,感谢大家捧场!!!


  1. 还是希望大家,可以多多评论区讨论 ↩︎

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

解决visio2021与本地家庭和学生版office21不兼容问题

原因分析 office 分为 MSI(windows Installer)和C2R(即点即用版本) 两个版本。 下载对应版本 可以看这个B站哥哥的资源&#xff1a;https://www.bilibili.com/read/cv17513800/ &#xff0c;选择标准离线版本安装

[单master节点k8s部署]37.微服务(一)springCloud 微服务

微服务架构的一个重要特点是&#xff0c;它与开发中使用的具体编程语言或技术栈无关。每个微服务都可以使用最适合其功能需求的语言或技术来实现。例如&#xff0c;一个微服务可以用Java编写&#xff0c;另一个微服务可以用Python、Go、Node.js等编写。微服务架构允许这种灵活性…

基于Arduino做的“鱿鱼游戏”BOSS面具,支持动作检测

这是一个结合了3D打印、舵机、PIR传感器和DFPlayer MP3模块的DIY项目&#xff0c;旨在制作一个带有动画眼睛的"鱿鱼游戏"老板面具。当检测到动作时&#xff0c;面具的眼睛会移动并播放声音&#xff0c;非常适合万圣节使用。 这个项目是一个很好的起点&#xff0c;特…

又一支付机构“经营异常”——易极付

近日&#xff0c;支付行业再次传出风波&#xff0c;重庆易极付科技有限公司&#xff08;简称“易极付”&#xff09;因“失联”问题被重庆两江新区市场监督管理局列入了经营异常名录。据天眼查平台显示&#xff0c;这一决定是基于“通过登记的住所或者经营场所无法联系”到该公…

【CSS in Depth 2 精译_050】7.3 CSS 响应式设计中的流式布局原则(Fluid layout)

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 【第七章 响应式设计】&#xff08;概述&#xff09; 7.1 移动端优先设计原则&#xff08;上篇&#xff09; 7.1.1 创建移动端菜单&#xff08;下篇&#xff09;7.1.2 给视口添加 meta 标签&#xf…

Linux Debian12基于ImageMagick图像处理工具编写shell脚本用于常见图片png、jpg、jpeg、tiff格式批量转webp格式

在Linux系统中&#xff0c;使用ImageMagick可以图片格式转换&#xff0c;其中最常用的是通过命令行工具进行。 ImageMagick是一个非常强大的图像处理工具集&#xff0c;它包含了许多用于图像转换的命令。 一、安装ImageMagick&#xff08;如果尚未安装&#xff09;&#xff1…

Python | Leetcode Python题解之第486题预测赢家

题目&#xff1a; 题解&#xff1a; class Solution:def PredictTheWinner(self, nums: List[int]) -> bool:length len(nums)dp [0] * lengthfor i, num in enumerate(nums):dp[i] numfor i in range(length - 2, -1, -1):for j in range(i 1, length):dp[j] max(num…

力扣21~30题

21题&#xff08;简单&#xff09;&#xff1a; 分析&#xff1a; 按要求照做就好了&#xff0c;这种链表基本操作适合用c写&#xff0c;python用起来真的很奇怪 python代码&#xff1a; # Definition for singly-linked list. # class ListNode: # def __init__(self, v…

leetcode30:串联所有单词的字串

给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。 s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。 例如&#xff0c;如果 words ["ab","cd","ef"]&#xff0c; 那么 "abcdef…

NetSarang Xshell v8.0060 Linux终端管理器个人免费版

NetSarang Xshell 官方个人完全免费中文版&#xff0c;Xshell特别版&#xff0c;Xshell 个人完全免费&#xff0c;Xshell 是一款最好用的Linux远程连接工具&#xff0c;免费SSH客户端、主机服务器远程管理客户端 。Xshell&#xff0c;轻松管理远程服务器&#xff0c;会话管理器…

《人工智能:CSDN 平台上的璀璨之星》

一、CSDN 上的 AI 热门话题 GPT-3 作为 CSDN 上的热门话题&#xff0c;其应用极为广泛。GPT-3 是 OpenAI 开发的一种基于 Transformer 架构的大规模预训练语言模型&#xff0c;拥有惊人的 1750 亿个参数。它具有多任务处理能力&#xff0c;能够执行多种自然语言处理任务&#x…

基于KNN算法的指纹定位系统(MATLAB,平面,四个锚点)

文章目录 指纹定位指纹定位技术简介基本原理位置估算公式1. 最近邻居算法&#xff08;KNN&#xff09;2. 加权最近邻居算法&#xff08;W-KNN&#xff09;3. 最小二乘法&#xff08;LS&#xff09; 最终位置 P P P通过求解下面的方程获得&#xff1a;应用场景优缺点优点缺点 总…

Python 工具库每日推荐 【pyspider 】

文章目录 引言网络爬虫的重要性今日推荐:pyspider 网络爬虫框架主要功能:使用场景:安装与配置快速上手示例代码代码解释实际应用案例案例:爬取新闻网站的文章案例分析高级特性使用代理处理 JavaScript 渲染的页面扩展阅读与资源优缺点分析优点:缺点:总结【 已更新完 Type…

《深度学习》OpenCV 风格迁移、DNN模块 案例解析及实现

目录 一、风格迁移 1、什么是风格迁移 2、步骤 1&#xff09;训练 2&#xff09;迁移 二、DNN模块 1、什么是DNN模块 2、DNN模块特点 1&#xff09;轻量 2&#xff09;外部依赖性低 3&#xff09;方便 4&#xff09;集成 5&#xff09;通用性 3、流程图 4、图像…

玛泽的故事中英文Big Muzzy台词本电子版PDF

《Big Muzzy》玛泽的故事&#xff0c;中英文都有&#xff0c;是BBC制作的&#xff0c;专为英语初学者设计的外语课程。它是教学动画里最有趣的一部&#xff01;风靡全球&#xff0c;上百个国家引进&#xff0c;深受小朋友的喜爱。《Big Muzzy》用动画的形式&#xff0c;讲述了M…

第九课:Python学习之函数基础

函数基础 目标 函数的快速体验函数的基本使用函数的参数函数的返回值函数的嵌套调用在模块中定义函数 01. 函数的快速体验 1.1 快速体验 所谓函数&#xff0c;就是把 具有独立功能的代码块 组织为一个小模块&#xff0c;在需要的时候 调用函数的使用包含两个步骤&#xff…

FFmpeg的简单使用【Windows】--- 指定视频的时长

目录 功能描述 效果展示 代码实现 前端代码 后端代码 routers 》users.js routers 》 index.js app.js 功能描述 此案例是在上一个案例【FFmpeg的简单使用【Windows】--- 视频混剪添加背景音乐-CSDN博客】的基础上的进一步完善&#xff0c;可以先去看上一个案例然后再…

C++核心编程和桌面应用开发 第十一天(静态转换 动态转换 常量转换 重新解释转换)

目录 1.静态类型转换 1.1语法 1.2用法 2.动态类型转换 2.1语法 2.2用法 3.常量类型转换 3.1语法 3.2用法 4.重新解释转换 4.1语法 1.静态类型转换 1.1语法 static_cast<目标转换类型>(待转换变量) 1.2用法 可用于基本数据类型之间的转换。比如int和char之…

2.线段求交

1.线段求交 给定由平面上 n 条闭线段构成的一个集合 S&#xff0c;报告出 S 中各线段之间的所有交点。 我们所希望得到的算法&#xff0c;其运行时间不仅取决于输入中线段的数目&#xff0c;还取决于&#xff08;实际的&#xff09;交点数目。这样的算法&#xff0c;被称为“输…

网络爬虫-数美滑块验证码

仅供研究学习使用。 今天带来的是数美滑块验证码的逆向 目标站 --> 传送门 解决此类验证码 首先要解决滑动距离的判定 无论是使用selenium还是使用协议的方式来破解 都绕不开滑动距离的识别 滑动距离可以参考以前我博客上的方式&#xff0c;或者找一找开源的一些算法&am…