当前位置: 首页 > wzjs >正文

网站开发用原生自己的网站如何让百度收录

网站开发用原生,自己的网站如何让百度收录,培训seo哪家学校好,有实力的网站建设推广本专栏内容均可在Github:notes_04 找到 完整项目使用技术栈: Nextjs15 MySQL Redis Auth Prisma i18n strapi Docker vercel 一、本节目标 本篇我们来实现右侧笔记CURD部分。 一、效果 当点击 New 按钮的时候进入编辑界面: 当点击…

本专栏内容均可在Github:notes_04 找到


完整项目使用技术栈: Nextjs15 + MySQL + Redis + Auth + Prisma + i18n + strapi + Docker + vercel

一、本节目标

本篇我们来实现右侧笔记CURD部分。

一、效果

当点击 New 按钮的时候进入编辑界面:

在这里插入图片描述

当点击具体笔记的 Edit 按钮的时候进入该笔记的编辑页面:

在这里插入图片描述

二、笔记预览

回忆下之前的路由设计,当点击 New 的时候,导航至 /note/edit 路由,当点击 Edit 的时候,导航至 /note/edit/xxxx 路由。

新增 app/note/edit/page.tsx

import NoteEditor from "../../components/NoteEditor";export default async function EditPage() {return <NoteEditor noteId={""} initialTitle="Untitled" initialBody="" />;
}

新增 app/note/edit/loading.tsx

export default function EditSkeleton() {return (<divclassName="note-editor skeleton-container"role="progressbar"aria-busy="true"><div className="note-editor-form"><div className="skeleton v-stack" style={{ height: "3rem" }} /><div className="skeleton v-stack" style={{ height: "100%" }} /></div><div className="note-editor-preview"><div className="note-editor-menu"><divclassName="skeleton skeleton--button"style={{ width: "8em", height: "2.5em" }}/><divclassName="skeleton skeleton--button"style={{ width: "8em", height: "2.5em", marginInline: "12px 0" }}/></div><divclassName="note-title skeleton"style={{ height: "3rem", width: "65%", marginInline: "12px 1em" }}/><div className="note-preview"><div className="skeleton v-stack" style={{ height: "1.5em" }} /><div className="skeleton v-stack" style={{ height: "1.5em" }} /><div className="skeleton v-stack" style={{ height: "1.5em" }} /><div className="skeleton v-stack" style={{ height: "1.5em" }} /><div className="skeleton v-stack" style={{ height: "1.5em" }} /></div></div></div>);
}

你可能会问,同级的 page.js 又没有数据请求,添加 loading.js 有什么用?

同级的 page.js 确实没有请求,但 loading.js 会将 page.js 和其 children 都包裹在 <Suspense> 中,所以 app/note/edit/[id]/page.tsx 中的请求也会触发该 loading.js

app/note/edit/[id]/page.tsx 代码如下:

import NoteEditor from "../../../components/NoteEditor";
import { getNote } from "@/lib/redis";export default async function EditPage({ params }: { params: { id: string } }) {const noteId = params.id;const note = await getNote(noteId);// 让效果更明显const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));await sleep(500);if (note === null) {return (<div className="note--empty-state"><span className="note-text--empty-state">Click a note on the left to view something! 🥺</span></div>);}return (<NoteEditornoteId={noteId}initialTitle={note.title}initialBody={note.content}/>);
}

我们抽离了一个 <NoteEditor> 组件用于实现编辑功能,app/components/NoteEditor.tsx 代码如下:

"use client";import { useState } from "react";
import NotePreview from "@/components/NotePreview";
import { useFormStatus } from "react-dom";export default function NoteEditor({ noteId, initialTitle, initialBody }) {const { pending } = useFormStatus();const [title, setTitle] = useState(initialTitle);const [body, setBody] = useState(initialBody);const isDraft = !noteId;return (<div className="note-editor"><form className="note-editor-form" autoComplete="off"><label className="offscreen" htmlFor="note-title-input">Enter a title for your note</label><inputid="note-title-input"type="text"value={title}onChange={(e) => {setTitle(e.target.value);}}/><label className="offscreen" htmlFor="note-body-input">Enter the body for your note</label><textareavalue={body}id="note-body-input"onChange={(e) => setBody(e.target.value)}/></form><div className="note-editor-preview"><form className="note-editor-menu" role="menubar"><buttonclassName="note-editor-done"disabled={pending}type="submit"role="menuitem"><imgsrc="/checkmark.svg"width="14px"height="10px"alt=""role="presentation"/>Done</button>{!isDraft && (<buttonclassName="note-editor-delete"disabled={pending}role="menuitem"><imgsrc="/cross.svg"width="10px"height="10px"alt=""role="presentation"/>Delete</button>)}</form><div className="label label--preview" role="status">Preview</div><h1 className="note-title">{title}</h1><NotePreview>{body}</NotePreview></div></div>);
}

因为需要控制输入框的状态,所以 <NoteEditor> 使用了客户端组件,我们在 <NotePreview> 中引用了 <NotePreview>组件,用于实现编辑时的实时预览功能。

三、笔记新增、更新、删除

当点击 Done 的时候,导航至对应的笔记预览页面 /note/xxxx。当点击 Delete 的时候,导航至首页。

正常开发笔记的增加、更新和删除功能,为了实现前后端交互,可能要写多个接口来实现,比如当点击删除的时候,调用删除接口,接口返回成功,前端跳转至首页。但既然我们都用了 Next.js 15 了,没必要这么麻烦,Server Actions 直接搞定,省的一个个写接口了。

修改 app/components/NoteEditor.tsx

"use client";import { useState } from "react";
import NotePreview from "./NotePreview";
import { useFormStatus } from "react-dom";
import { deleteNote, saveNote } from "../actions";
export default function NoteEditor({noteId,initialTitle,initialBody,
}: {noteId: string;initialTitle: string;initialBody: string;
}) {const { pending } = useFormStatus();const [title, setTitle] = useState(initialTitle);const [body, setBody] = useState(initialBody);const isDraft = !noteId;return (<div className="note-editor"><form className="note-editor-form" autoComplete="off"><label className="offscreen" htmlFor="note-title-input">Enter a title for your note</label><inputid="note-title-input"type="text"value={title}onChange={(e) => {setTitle(e.target.value);}}/><label className="offscreen" htmlFor="note-body-input">Enter the body for your note</label><textareavalue={body}id="note-body-input"onChange={(e) => setBody(e.target.value)}/></form><div className="note-editor-preview"><form className="note-editor-menu" role="menubar"><buttonclassName="note-editor-done"disabled={pending}type="submit"formAction={() => saveNote(noteId, title, body)}role="menuitem">Done</button>{!isDraft && (<buttonclassName="note-editor-delete"disabled={pending}formAction={() => deleteNote(noteId)}role="menuitem">Delete</button>)}</form><div className="label label--preview" role="status">Preview</div><h1 className="note-title">{title}</h1><NotePreview>{body}</NotePreview></div></div>);
}

新增:app/actions.tsx

"use server";import { redirect } from "next/navigation";
import { addNote, updateNote, delNote } from "@/lib/redis";export async function saveNote(noteId: string, title: string, body: string) {const data = JSON.stringify({title,content: body,updateTime: new Date(),});if (noteId) {updateNote(noteId, data);redirect(`/note/${noteId}`);} else {const res = await addNote(data);redirect(`/note/${res}`);}
}export async function deleteNote(noteId: string) {delNote(noteId);redirect("/");
}

至此 新增和删除可以正常运行了:

在这里插入图片描述


文章转载自:

http://wTqJON1x.pLhhd.cn
http://LSnx5aF4.pLhhd.cn
http://qWiKr8M6.pLhhd.cn
http://vfmgGPCu.pLhhd.cn
http://TTXFm62Q.pLhhd.cn
http://nOnpB89d.pLhhd.cn
http://UDwZ98Ln.pLhhd.cn
http://YgtcECeY.pLhhd.cn
http://sm5dDmx8.pLhhd.cn
http://5QBWZL4W.pLhhd.cn
http://4XQ2HlG7.pLhhd.cn
http://ZEWLDJ8q.pLhhd.cn
http://7lsfW7NU.pLhhd.cn
http://G5MpHFVv.pLhhd.cn
http://cF8Geuxc.pLhhd.cn
http://sQS5uKO2.pLhhd.cn
http://7nppBh2V.pLhhd.cn
http://oLDrYLoR.pLhhd.cn
http://pjAeLQUL.pLhhd.cn
http://ThHOXoDv.pLhhd.cn
http://sZadVJXX.pLhhd.cn
http://Q6NG3xBA.pLhhd.cn
http://PsR6sWiK.pLhhd.cn
http://cHouHkL4.pLhhd.cn
http://YSMpV884.pLhhd.cn
http://0KVUut4p.pLhhd.cn
http://x6GCYt9d.pLhhd.cn
http://tAQdOlqp.pLhhd.cn
http://hWWcZnhH.pLhhd.cn
http://1qjZLCVM.pLhhd.cn
http://www.dtcms.com/wzjs/662221.html

相关文章:

  • seo门户网站建设方案西安网站建设资讯
  • 在阿里巴巴上做网站需要什么建立一个网页需要多少钱
  • 新乡网站建设多少钱网站内备案名称 修改
  • 西安网站建设第一品牌wordpress怎么调度主题
  • 网站建设与维护笔记软件设计公司
  • 网站做多少分辨率哈尔滨建设公司网站
  • 巴中市建设局网站小区网站建设方案怎么写
  • 上饶哪有做网站的公司域名注册信息
  • 海口有做棋牌娱乐网站的吗鼓楼做网站公司哪家好
  • 猎奇网站模板兼职网站制作
  • 广西住房和城乡建设厅网站证件免费制作论坛网站模板
  • 网站建设费用价格明细表鞋材 技术支持 东莞网站建设
  • 如何建立p2p网站android手机开发工具
  • 做公司网站500元域名到期怎么续费
  • 10m带宽做下载网站什么网站做ppt模板
  • 广州网站seo招聘网上商城取名
  • 网站建设都一般步骤网站开发质量管理
  • 数学网站怎么做做网站买一个域名多少钱
  • 普通的宣传网站用什么做临沂市建设局兰山区网站
  • 建站程序免费下载赣州有没有做网站的
  • 北京小程序开发推荐青岛信息优化排名推广
  • 网吧手机网站模版网站开发 文学
  • 乔智云智能建站计算科学与学习网站建设与实施
  • 为网站网站做代理怎么判怎么做网站的产品分析
  • 仿别人网站网站怎么做全屏的
  • 网站建设师菏泽建设公司网站
  • 建设网站和ipv4和ipv6什么关系外贸买家网站
  • 网站建设费可分摊几年wordpress获取页面正文
  • 爱站工具seo综合查询仓库管理系统app
  • 云南旅行社网站设计大连建设工程信息网查询