Web 编写 22

news/2025/10/15 18:41:30/文章来源:https://www.cnblogs.com/yxysuanfa/p/19144024

1 div和p可以乱写吗?

在 HTML 中,<div> 和 <p> 标签都有其特定的语义和使用规范,不能 “乱写”,需要遵循一定的规则:

1. <div> 标签

  • 语义div 是 “division”(分区、划分)的缩写,是一个通用的块级容器标签,没有特定的语义,主要用于对页面内容进行分组,以便通过 CSS 样式或 JavaScript 进行统一操作。
  • 使用规范
    • 可以用来划分页面的不同区域,比如头部(header)、主体(main)、底部(footer)、侧边栏(sidebar)等。
    • 当没有更合适的语义化标签(如 <header><section><article> 等)时,可用 div 来包裹内容。

2. <p> 标签

  • 语义p 是 “paragraph”(段落)的缩写,专门用于表示一个段落的文本内容。
  • 使用规范
    • 只能用于包裹段落文本,每个 p 标签代表一个独立的段落。
    • 它是一个块级元素,默认情况下,段落之间会有一定的间距(由浏览器默认样式决定,可通过 CSS 调整)。

为什么不能 “乱写”

  • 语义化:HTML5 强调语义化,使用合适的标签能让页面结构更清晰,便于搜索引擎优化(SEO),也方便屏幕阅读器等辅助设备理解页面内容,提升无障碍访问性。
  • 样式与行为:不同的标签在浏览器中有默认的样式和行为,遵循规范使用标签,能减少 CSS 样式和 JavaScript 行为处理的复杂度。比如 p 标签默认有上下外边距,而 div 没有,如果错误地用 div 来表示段落,可能需要额外编写 CSS 来模拟段落的间距效果。

正确示例

Example

Page Title

This is a paragraph. It contains some text that forms a single paragraph.

This is another paragraph. Each p tag represents a separate paragraph.

Section Title

Content in this section...

在这个示例中,div 用于划分页面的容器和 section 区域,p 用于表示段落文本,结构清晰且符合语义规范。

【其实功能是不是不影响的,只是不合规范和代码可读性?】

从功能实现的角度看,单纯为了让页面呈现出某种样式或布局,用错误的标签也可能暂时达到效果,但从更重要的层面来说,标签的正确使用(语义化)影响很大,不只是规范和可读性的问题,还涉及以下关键方面:

1. 对浏览器与工具的影响

  • 搜索引擎优化(SEO):搜索引擎(如谷歌、百度)的爬虫会通过标签的语义来理解页面内容的结构和层级。比如,<h1> - <h6> 标签能让爬虫识别标题的重要性和层级关系,<article> 标签能明确这是一篇独立的文章内容。如果滥用 <div> 代替这些语义化标签,爬虫难以准确抓取内容的核心逻辑,会降低页面在搜索结果中的排名。
  • 无障碍访问(Accessibility):屏幕阅读器等辅助设备依赖标签的语义来为视障用户解读页面。例如,<nav> 标签会让屏幕阅读器知道这是导航区域,用户能快速定位;若用 <div class="nav">,辅助设备无法直接识别,视障用户获取信息的效率会大大降低。
  • 浏览器默认行为与样式:不同标签有默认的行为和样式。比如 <a> 标签默认有下划线且带有链接行为,<button> 标签默认有按钮的交互样式和焦点行为;若用 <div> 模拟按钮,需要手动添加大量 CSS 样式和 JavaScript 事件(如点击反馈、焦点管理等),既繁琐又容易遗漏细节。

2. 代码维护与协作

  • 可读性:语义化的标签能让代码 “自解释”。当团队协作或后续自己维护代码时,看到 <section> 就知道这是一个区块,看到 <p> 就知道是段落,能快速理解页面结构,提高开发效率;而满是 <div> 的代码,需要通过类名或注释才能推测用途,维护成本高。
  • 可扩展性:基于语义化标签构建的页面,在后续功能扩展或样式调整时更顺畅。比如要给所有文章区块添加统一样式,只需针对 <article> 标签编写 CSS;若用 <div class="article">,一旦类名命名不统一或后续需要修改类名,调整范围会更大。

举个例子

如果要做一个博客页面,正确的语义化结构可能是:

博客标题

文章标题

文章段落内容...

另一篇文章标题

另一篇文章段落内容...

版权信息

如果全部用 <div> 代替:

博客标题
文章标题
文章段落内容...
另一篇文章标题
另一篇文章段落内容...

虽然通过 CSS 也能让页面看起来一样,但前者对搜索引擎、辅助设备更友好,代码也更易读、易维护。

所以,标签的正确使用(语义化)不只是规范和可读性,更关系到页面的可访问性、SEO 表现以及长期的可维护性,并非 “功能不影响”。

2  分析Tailwind CSS 构建界面的 HTML 代码

这是一段使用 Tailwind CSS 构建界面的 HTML 代码,结合代码和右侧预览效果,我们从多个方面详细分析:

一、整体结构与语义化标签

  • <section> 标签作为 HTML5 的语义化标签,用于定义文档中的一个章节、区段。在这里,它包裹了整个界面内容,起到划分页面模块的作用,让页面结构更清晰,也有利于搜索引擎优化和无障碍访问。
  • 类名与 Tailwind CSSclass="bg-gray-900 w-full p-4" 是 Tailwind CSS 的实用类。
  • bg-gray-900 设置背景颜色为深灰色;
  • w-full 表示宽度占满父容器;
  • p-4 是内边距(padding)为 4 个单位(Tailwind 默认的单位是基于设计系统的,可通过配置调整)。

二、顶部区域(由第一个 <div> 包裹)

  • 布局类 flex justify-betweenflex 启用 Flex 布局,justify-between 让 Flex 容器内的子元素(两个 <p> 标签)在水平方向上两端对齐,中间间距自动分配,实现了 “Close” 在左、“Drafts” 在右的布局效果。
  • 文本样式类
    • 第一个 <p> 标签的 text-white 使文字颜色为白色,与深灰色背景形成对比,便于阅读。
    • 第二个 <p> 标签的 text-blue-400 font-semiboldtext-blue-400 设置文字为浅蓝色,font-semibold 让字体粗细为半粗体,突出 “Drafts” 这个文本。

三、中间内容区域(由第二个 <div> 包裹)

  • 布局与尺寸类flex gap-4 py-8 h-48flex 同样是 Flex 布局;gap-4 设置 Flex 项目之间的间距为 4 个单位;py-8 是垂直方向(上下)的内边距为 8 个单位;h-48 设定容器高度为 48 个单位。
  • 圆形区域(嵌套的 <div>w-16 h-16 aspect-square bg-blue-400 rounded-fullw-16 h-16 设置宽度和高度均为 16 个单位;
  • aspect-square 确保元素是正方形(宽高比为 1:1);
  • bg-blue-400 背景为蓝色;
  • rounded-full 让元素变成圆形,这是 Tailwind 中制作圆形元素的常用方式(将正方形的 border-radius 设为 50%)。
  • 文本输入区域(<textarea>
    • w-full mt-4 bg-transparent text-white text-2xl focus:outline-nonew-full 宽度占满;mt-4 顶部外边距为 4 个单位;bg-transparent 背景透明,与父容器背景融合;text-white text-2xl 文字为白色且字号为 2xl(Tailwind 预设的字号等级);focus:outline-none 移除了输入框获取焦点时的默认外轮廓线,可根据需要自定义焦点样式。
    • placeholder="What is happening?!" 设置占位文本,提示用户在此输入内容。

四、底部区域(<p> 和 <hr> 标签)

  • 文本样式font-bold text-blue-400font-bold 字体为粗体,text-blue-400 文字为浅蓝色,突出 “Everyone can reply” 这段文字。
  • 分隔线(<hr>border-gray-500 my-4border-gray-500 设置边框颜色为浅灰色;my-4 是垂直方向(上下)的外边距为 4 个单位,用于在文本和下方内容(如果有)之间创建间距。

扩展知识 ——Tailwind CSS 相关

Tailwind CSS 是一种实用优先(Utility-First)的 CSS 框架,它通过提供大量预定义的实用类,让开发者可以直接在 HTML 中通过类名来快速构建界面,而无需编写大量自定义 CSS。

  • 实用类的优势
    • 开发效率高:无需切换到 CSS 文件编写样式,在 HTML 中就能完成大部分样式设置。
    • 样式一致性:基于 Tailwind 的设计系统,能保证项目中样式的一致性,比如颜色、间距、字号等都遵循预设的比例和规范。
    • 可定制性:通过配置文件(tailwind.config.js),可以自定义颜色主题、字体、间距等,满足项目特定需求。
  • 响应式设计:Tailwind 支持响应式前缀,比如 md:w-1/2 表示在中等屏幕(md 断点)及以上时,宽度为父容器的一半。在复杂界面中,可利用这些前缀轻松实现响应式布局。
  • 自定义工具类:如果 Tailwind 提供的实用类无法满足需求,还可以通过 @utility 指令(在使用 Tailwind 插件或自定义配置时)创建自定义的实用类,进一步扩展功能。

通过这段代码,能很好地体现 Tailwind CSS 实用优先的特点,以及 HTML5 语义化标签在页面结构组织上的作用,整体构建出一个简洁且具有一定交互提示(如占位文本、可回复提示)的界面区域。

3 必须使用setState来更新状态

在 React 中,必须使用 setState(或函数组件中 useState 返回的状态更新函数,如图中的 setState1)来更新状态,而不是直接赋值,主要有以下关键原因:

1. 触发组件重新渲染

React 组件的渲染是由状态(State)和属性(Props)驱动的。

当使用 setState(或状态更新函数)更新状态时,React 会知道状态发生了变化,进而触发组件的重新渲染流程。

如果直接对状态变量进行赋值(比如 state1 = 2),React 内部的状态管理机制无法感知到这种变化,组件不会重新渲染,页面也就不会更新为新的状态对应的视图。

例如,在图中的函数组件里,state1 是通过 useState(1) 声明的状态变量,当调用 setState1(2) 时,组件会重新渲染,{state1} 对应的位置会显示 2

但如果直接写 state1 = 2,组件不会重新渲染,页面上依然显示 1

2. 异步更新与批量处理

React 会对 setState 进行优化,将多个状态更新进行批量处理,以提高性能。

setState 本身是异步的(在大多数情况下,React 会将状态更新延迟到合适的时机,比如事件循环的下一个周期)。这种异步和批量处理的机制,能避免频繁地重新渲染组件,减少性能开销。

如果直接赋值,无法利用 React 这种优化机制,可能导致多次不必要的渲染,或者状态更新不符合预期(因为直接赋值是同步的,无法和其他状态更新一起批量处理)。

3. 状态管理的一致性

React 内部通过一套完整的状态管理机制来维护组件的状态,包括状态的存储、更新调度以及与组件渲染的关联等。

setState 是与这套机制交互的 “官方接口”,它确保了状态更新的流程是规范且可预测的。直接赋值会绕过这套机制,破坏状态管理的一致性,可能引发各种难以调试的问题,比如状态不同步、组件生命周期方法执行异常等。

总结

简单来说,setState(或函数组件的状态更新函数)是 React 为了让开发者能够正确、高效地更新组件状态,并触发组件重新渲染而提供的机制。

直接赋值无法让 React 知晓状态变化,也就无法完成组件的重新渲染和相关的优化处理,所以必须使用 setState 系列方法来更新状态。

4  HTTP(超文本传输协议)的核心概念与常见操作

1. HTTP 的核心定位:互联网通信的 “语言”

HTTP 是互联网上客户端(如浏览器、前端应用)与服务器之间传递数据、交互通信的协议。它规定了客户端如何向服务器请求资源,以及服务器如何向客户端返回响应的 “规则”。

2. GET 请求:获取信息

  • 核心作用:向服务器请求已有的资源或数据(比如 “查询某条订单”“获取用户信息”)。
  • 前端 → 后端:传递参数的方式
    • 通过 URL 查询参数(即 URL 中 ? 后的键值对,如 https://example.com/user?name=Alice&age=25)传递信息。
    • 在后端(以 Node.js + Express 为例),通过 req.query 来获取这些参数。比如前端请求 ?name=Alice,后端可写 const name = req.query.name 拿到 Alice
  • 特点与限制
    • 是 “安全” 且 “幂等” 的请求(多次请求同一 URL,结果一致,不会修改服务器数据)。
    • 但 URL 长度有限(不同浏览器 / 服务器限制不同,通常几千字符),且参数会暴露在 URL 中,不适合传递敏感信息(如密码)。

3. POST 请求:新增信息

  • 核心作用:向服务器提交新数据,让服务器创建资源(比如 “提交订单”“注册新用户”)。
  • 前端 → 后端:传递数据的方式
    • 通过 请求体(Request Body) 传递数据(数据放在 HTTP 报文的 “body” 部分,而非 URL)。
    • 在后端(以 Node.js + Express 为例),需配合中间件(如 express.json() 解析 JSON 格式、express.urlencoded() 解析表单格式),然后通过 req.body 获取数据。比如前端提交 JSON 格式的订单信息,后端可写 const orderData = req.body 拿到完整数据。
  • 特点
    • 可传递大量、复杂的数据(不受 URL 长度限制)。
    • 适合传递敏感信息(因为数据在请求体中,不会直接暴露在 URL)。
    • 不是 “幂等” 的(多次提交同一 POST 请求,可能重复创建资源,比如 “重复下单” 会生成多个订单)。

4. Response:服务器向客户端返回信息

  • 核心作用:服务器处理完请求后,向客户端回传数据或结果(比如 “返回订单详情”“告知注册是否成功”)。
  • 后端 → 前端:返回数据的方式
    • 在后端(以 Node.js + Express 为例),通过 res.send(<object>) 发送响应。可以返回字符串、JSON 对象等。比如 res.send({ success: true, data: { name: "Alice" } }),前端就能收到这个 JSON 数据。
  • 扩展:除了 res.send,还有更细分的方法,比如 res.json() 专门返回 JSON 数据,res.status(404).send("Not Found") 附带状态码返回信息等。

5. HTTP 与 API 的关系

API(应用程序接口)是不同系统之间交互的 “接口”,而 HTTP 是 API 最常用的通信协议。例如:

  • 前端应用通过 HTTP 请求调用 “用户管理 API”,实现 “查询用户”“创建用户”。
  • 移动应用通过 HTTP 请求调用 “天气 API”,获取实时天气数据。

6. 幻灯片底部的示例(强化 GET/POST 场景)

  • GET /store/order/{orderId}:通过 GET 请求,根据 orderId(订单 ID)查询某条订单的详情(符合 “GET → 获取已有信息” 的逻辑)。
  • POST /store/order:通过 POST 请求,提交 “下单” 的新数据,让服务器创建一条新订单(符合 “POST → 新增信息” 的逻辑)。

总结

HTTP 是前后端(或客户端 - 服务器)通信的基础协议,GET 用于 “查”,POST 用于 “增”,而 req.query/req.body(后端获取前端数据)、res.send(后端返回前端数据)是具体的技术实现方式(以 Node.js + Express 为例)。理解这些,是前端与后端协作、调用 API 的核心基础。

5 API(应用程序编程接口)的知识回顾

1. API 的本质:一套 “规则”

API 不是具体的 “代码文件” 或 “程序”,而是客户端(如前端应用、手机 App)与服务器之间交互的 “规则约定”。它规定了:

  • 客户端如何向服务器 “请求数据或功能”;
  • 服务器如何向客户端 “返回结果或响应”。

打个比方:API 就像餐厅的 “菜单”—— 菜单上的菜品名称、下单方式(比如扫码、喊服务员),就是 “规则”;你(客户端)通过菜单点单,厨房(服务器)根据菜单做餐并上菜,就是 “交互流程”。

2. API 的作用:描述 “如何从服务器获取数据”

API 定义了数据交互的逻辑和格式。比如:

  • 要获取 “故事列表”,应该用什么 URL(如 /api/stories)?
  • 用什么请求方式(如 GET/POST)?
  • 服务器返回的数据是什么格式(如 JSON)?

没有 API,客户端和服务器就会 “鸡同鸭讲”—— 客户端不知道怎么要数据,服务器也不知道怎么给数据。

3. API 端点(API Endpoints):可调用的 “功能接口”

“API 端点” 是 API 中具体的 “功能入口”。每个端点对应一个 “动作” 或 “数据资源”。

比如幻灯片中的 api/stories 就是一个端点:它的作用是 “获取所有故事数据”。你可以把端点理解为 “函数名”—— 调用这个 “函数”(发送请求到该端点),就能得到对应的 “功能结果”(故事数据)。

4. 前后端交互流程(结合示例理解)

幻灯片用 “前端(Frontend)→ 后端(Backend)” 的交互,演示了 API 的工作过程:

步骤 1:前端发起请求(req

前端通过代码(如 get("/api/stories")),向服务器的 api/stories 端点发送请求(Request,简称 req)。这个请求的意图是:“我要获取所有故事数据”。

步骤 2:后端处理请求

后端(比如用 Node.js + Express 框架)通过代码:

app.get("api/stories", (req, res) => {res.send(data.stories);
});

接收并处理请求

  • app.get(...) 表示 “监听 GET 类型的请求,路径是 api/stories”;
  • 当请求到达时,执行回调函数,把 data.stories(假设是后端存储的 “故事列表” 数据)准备好。
步骤 3:后端返回响应(res

后端通过 res.send(data.stories),把 “故事列表” 作为响应(Response,简称 res),返回给前端。

步骤 4:前端接收数据

前端收到响应后,就能拿到类似这样的故事数据:

{"content": "I love dancing!","creator_name": "Nicholas Tsao","_id": 0
}

然后前端可以把这些数据渲染到页面上(比如显示 “故事内容”“创作者名字” 等)。

5. 扩展:API 的更多细节

  • 请求方式多样性:除了 GET(获取数据),还有 POST(提交新数据,比如 “新增故事”)、PUT(修改已有数据)、DELETE(删除数据)等。不同的请求方式,对应不同的 “数据操作意图”。
  • 数据格式约定:API 通常用 JSON 或 XML 格式传递数据(幻灯片中用的是 JSON),这样前后端都能轻松解析和处理。
  • API 安全性:实际开发中,API 还会涉及 “身份验证”(如 Token 机制)、“权限控制”(如某些接口只有登录用户能调用)等,确保数据交互的安全。

总结

API 是前后端(或客户端 - 服务器)之间的 “通信语言”:通过 “规则约定”,定义 “如何请求数据”“如何返回数据”;而 “API 端点” 是具体的 “功能入口”,让前端能精准调用后端的功能或数据。理解 API,是前端与后端协作、开发 “能联网的应用” 的核心基础。

6 JavaScript 异步编程 的核心概念与 Promise 作用

1. JavaScript 是 “异步语言” 的核心原因

JavaScript 运行在单线程环境中(为了避免复杂的线程同步问题),但又需要处理耗时操作(比如网络请求、读取文件)。如果采用 “同步” 方式(即 “等一个操作完成,再执行下一个操作”),会导致线程被阻塞,页面卡死(比如浏览器中,同步的网络请求会让页面无法交互)。

因此,JavaScript 天生支持异步编程—— 发起耗时操作后,不会 “等待它完成”,而是继续执行后续代码;等耗时操作完成后,再通过 “回调” 等方式处理结果。

2. API 请求的异步特性

幻灯片中提到 “We cannot wait for an API request to complete before executing more code”,意思是:当我们发起一个 “API 请求”(比如从服务器获取宠物信息),这个过程是耗时的(网络传输、服务器处理都需要时间)。如果 JavaScript 同步等待这个请求完成,整个程序就会 “卡住”。

所以,API 请求必须以异步方式执行 —— 发起请求后,JavaScript 继续执行后续代码;等请求响应回来后,再处理数据。

3. Promise 的作用

为了解决异步操作的 “回调地狱”(多个异步操作嵌套,代码可读性极差),JavaScript 引入了 PromisePromise 是一种异步操作的 “承诺”

  • 它表示 “现在发起异步操作,未来某个时刻会得到结果(成功或失败)”;
  • 可以通过 .then()(处理成功结果)、.catch()(处理失败结果)等方法,优雅地串联异步操作。

4. 代码示例分析(回答 “打印什么” 的问题)

看幻灯片中的代码:

let petName = "undecided";
get("/pet/0").then((pet) => {petName = pet.name; // 假设 pet.name 是 "Tim the Beaver"
});
console.log(petName);

1. 变量与异步操作的本质

  • 代码中 get("/pet/0") 是一个异步操作,它会向服务器发送请求获取宠物信息。
  • petName 初始化为 "undecided"

2. 执行顺序的关键

  • 当执行到 get("/pet/0").then(...) 时,JavaScript 会立即发起这个异步请求,然后继续执行后面的代码(也就是 console.log(petName)),不会等待请求完成。
  • 但是,异步请求的响应时间是不确定的—— 它可能非常快(比如本地模拟接口),也可能很慢(网络差的情况)。

3. 对 “打印结果” 的判断

题目里的选项是:

  • a. undecided
  • b. Tim the Beaver
  • c. Unable to be determined

因为我们无法提前确定异步请求的响应速度:

  • 如果 console.log 执行时,异步请求还没完成,那么 petName 是 "undecided"(对应选项 a)。
  • 如果 console.log 执行时,异步请求已经完成,那么 petName 已经被改为 "Tim the Beaver"(对应选项 b)。

由于代码中没有任何逻辑能保证 “异步请求的完成时机”(比如没有同步锁、没有明确的顺序控制),所以最终打印结果是 “无法确定的”—— 它可能是 a,也可能是 b,取决于运行时的网络、服务器响应等不可控因素。

扩展:如何让代码按 “预期顺序” 执行?

如果想让 console.log 打印出 "Tim the Beaver",需要让它在异步请求完成后执行。可以用以下方式:

方式 1:把 console.log 放到 .then() 里
get("/pet/0").then((pet) => {petName = pet.name;console.log(petName); // 现在会打印 "Tim the Beaver"
});
方式 2:使用 async/await(更简洁的异步语法)
async function getPetName() {let petName = "undecided";const pet = await get("/pet/0"); // 等待异步请求完成petName = pet.name;console.log(petName); // 打印 "Tim the Beaver"
}
getPetName();

async/await 是基于 Promise 的语法糖,让异步代码看起来像 “同步代码” 一样直观。

总结

JavaScript 的异步特性决定了 “耗时操作(如 API 请求)不会阻塞后续代码执行”,Promise(及 async/await)是处理异步流程的核心工具。理解 “异步执行顺序” 是掌握 JavaScript 异步编程的关键。

7 在服务器的变量中存储数据存在的问题

1. 核心问题:“服务器变量存储数据” 的临时性

代码中用 let data = {...} 在服务器内存里定义变量存储数据(比如故事列表),这种方式的本质是 “把数据存在服务器的‘运行内存’中”

而服务器的 “运行内存” 是临时的—— 只要服务器的运行状态被中断,内存里的数据就会丢失。

2. 哪些场景会导致 “服务器运行中断”?

幻灯片列举了几个典型场景:

  • 关闭终端(You close Terminal):如果是在本地终端启动的服务器(比如用 node app.js 启动),关闭终端会直接终止服务器进程。
  • 修改服务器代码(You modify your server code):修改代码后,通常需要重启服务器才能让新代码生效,重启会清空内存。
  • 服务器崩溃(Your server crashes):服务器因错误(如代码异常、内存溢出)意外停止,进程终止。
  • 笔记本没电(Your laptop runs out of battery):设备断电,服务器进程被迫终止。

3. 后果:“所有数据丢失(All your data is gone)”

因为数据只存在运行内存里,一旦服务器进程终止,内存被释放,data 变量里的内容(比如故事列表、用户数据)就会完全丢失。

打个比方:这就像 “把文件存在电脑的‘内存临时区域’,而不是硬盘里”—— 电脑重启(或程序重启),临时区域的文件就没了。

4. 扩展:如何解决 “数据持久化” 问题?

为了让数据在服务器重启后也能保留,需要“数据持久化”方案,常见方式有:

  • 数据库(Database):把数据存在专门的数据库中(如 MySQL、MongoDB、SQLite 等)。数据库会将数据写入磁盘,即使服务器重启,磁盘里的数据依然存在。
  • 文件存储:把数据以文件形式(如 JSON 文件、CSV 文件)写入服务器的磁盘。下次服务器启动时,再从文件中读取数据。

总结

“在服务器变量中存数据” 的最大问题是 “数据不持久”—— 服务器一旦重启或崩溃,数据就会丢失。因此,实际开发中,重要数据需要用 “数据库” 或 “文件存储” 等持久化方式来保存。

即使假设服务器永远不重启,当出现以下情况时(比如类似 “Catbook” 的应用有数千用户,需要存储千兆字节的故事和评论数据),只在服务器变量里存数据会导致内存(RAM)耗尽,进而引发服务器崩溃。因为计算机的内存资源是有限的,无法无限制地存储大量数据。

用 data.txt 这类普通文本文件存储数据存在的问题

这张幻灯片分析了用 data.txt 这类普通文本文件存储数据存在的问题,下面逐一解释并扩展:

1. 写入速度(Write Speed)

  • 问题:每当有用户发布新故事或评论时,都要往 data.txt 里写数据。但文本文件的写入操作相对较慢(需要磁盘 I/O,即和硬盘交互),如果用户量大、发布频繁,写入操作会成为性能瓶颈。
  • 扩展:比如一个社交平台,每秒有上百条新动态,每次写文本文件都要 “打开文件→写入内容→保存关闭”,硬盘的读写速度远赶不上内存操作,会导致用户发布内容时 “卡顿”。

2. 内存使用(Memory Usage)

  • 问题:为了能快速操作数据,通常会把 data.txt 里的所有故事、评论都加载到内存(RAM)中。但数据量一旦大起来(比如百万条评论),会占用大量内存,甚至导致内存不足。
  • 扩展:假设每条故事平均占 1KB,100 万条就占 1GB 内存;如果是更复杂的内容,内存占用会更夸张,可能让服务器因内存不足而崩溃。

3. 查询速度(Query Speed)

  • 问题:如果要找一个特定 _id 的故事,需要线性遍历所有故事(即从第一条开始,逐个检查 _id 是否匹配)。数据量越大,遍历时间越长,查询越慢。
  • 扩展:比如要找 _id = 10000 的故事,若有 10 万条数据,最坏情况要遍历 10 万次才找到,这在用户体验上是无法接受的(页面可能转圈圈好几秒)。

4. 单点故障(Single Point of Failure)

  • 问题:如果存储 data.txt 的笔记本硬盘坏了,所有数据都会丢失,没有备份。
  • 扩展:现实中,硬盘是机械 / 电子设备,有损坏风险;而企业级应用需要 “高可用性”,即数据不能因为某一个硬件损坏就丢失,所以文本文件存储无法满足这种需求。

5. 并发问题(Concurrency Issues)

  • 问题:如果两个用户同时发布内容,同时往 data.txt 写数据,容易出现 “数据覆盖” 或 “写入混乱”。Node.js 文档也指出:不等待回调就多次对同一文件用 fs.write() 是不安全的。
  • 扩展:比如用户 A 和用户 B 同时写 data.txt,A 的写入可能被 B 覆盖,最终只保留 B 的内容;或者写入的内容混杂在一起,导致数据错误。

总结

用普通文本文件(如 data.txt)存储数据,在性能、可靠性、并发支持等方面都有明显缺陷,无法满足中大型应用的需求。这也是为什么实际开发中,会使用专门的数据库(如 MySQL、MongoDB)来管理数据 —— 数据库在 “高效读写”“索引查询”“容灾备份”“并发控制” 等方面都做了专业优化。

9 数据库和数据库管理系统

数据库(Database,DB)

数据库是有组织的数据集合

这里的 “有组织” 意味着数据不是杂乱无章地堆积,而是按照特定的结构(比如表格、关系模型等)进行存储,以便于后续的查找、使用等操作。

打个比方,就像图书馆里的书籍,不是随意堆放,而是按照分类(如文学、科学、历史等)、作者、书名等规则有序排列,这样人们能快速找到想要的书籍。数据库里的数据也类似,比如一个电商平台的数据库,会把商品信息(名称、价格、库存)、用户信息(账号、地址、订单记录)等,都以结构化的方式存储,方便后续查询某件商品的库存,或者某个用户的历史订单。

数据库管理系统(Database Management System,DBMS)

数据库管理系统是一组功能的集合,这些功能让用户能够对数据库里的数据进行检索(查询)、添加、修改、删除操作。

简单来说,DBMS 是用户和数据库之间的 “桥梁”。没有 DBMS 的话,用户很难直接对数据库里的海量数据进行高效操作。比如,当我们想从电商平台的数据库里查询某款销量最高的商品时,就是通过 DBMS 提供的检索功能来实现;如果要上架一款新商品,就用 DBMS 的添加功能把新商品数据存入数据库;商品价格调整时,用修改功能更新价格数据;商品下架了,就用删除功能移除相关数据。

常见的 DBMS 有 MySQL、Oracle、SQL Server 等。不同的 DBMS 有各自的特点,像 Oracle 常用于大型企业级应用,能处理海量数据和高并发访问;MySQL 则因为开源、轻量,在中小型应用和互联网项目中广泛使用。

此外,DBMS 还承担着很多重要任务,比如数据完整性维护(确保数据准确、一致,比如设定商品价格不能为负数)、数据安全性管理(控制哪些用户能访问哪些数据,防止数据泄露)、并发控制(当多个用户同时操作数据库时,保证数据操作的正确性,避免冲突)等。

10 数据库类型

关系型数据库(SQL)。

关系型数据库以类似电子表格(表格)的格式存储数据。比如示例中的 “Stories” 表,有_id(编号)、creator_name(创作者姓名)、content(内容)等列,每一行代表一条记录。

常见的关系型数据库有 SQLite、MySQL、PostgreSQL 等,它们广泛应用于需要结构化存储和管理数据的场景,像企业管理系统、电商平台的数据存储等,能通过 SQL(结构化查询语言)方便地进行数据的查询、插入、更新和删除等操作。

文档数据库(NoSQL)。

文档数据库存储 “文档”,这些文档本质上是 JSON 对象。

例如图中 “Stories” 里的内容,就是以类似 JSON 对象的形式存储,每个文档有_id(编号)、creator_name(创作者姓名)、content(内容)等字段。

常见的文档数据库有 MongoDB,它在设置和使用相关功能方面,相对来说更容易上手,适合那些数据结构不太固定、需要灵活存储的场景,像社交应用中的动态内容、博客平台的文章数据等存储。

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

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

相关文章

svn 忽略选项还原

svn 忽略选项还原svn 忽略出现问题导致项目新添加的文件无法自动 Add,或其它问题。 解决办法:在项目根目录内空白处,右键弹出菜单选择 properties,然后修改 svn:ignore 和其它正常项目一样即可。桂棹兮兰桨,击空明…

【html】canvas实现一个时钟 - 实践

【html】canvas实现一个时钟 - 实践2025-10-15 18:39 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !imp…

特殊函数

> C语言三大特殊函数:静态函数(缩小可见域)、递归函数(自我调用)、回调函数(钩子/函数指针)。一、静态函数:文件级私有化背景知识: 普通函数都是跨文件可见的,即在文件 a.c 中定义的函数可以在 b.c 中使用…

一行代码也能行?极简实现GPIO按键关机(支持短按/长按)

别被复杂的逻辑吓到!其实用极简代码就能实现GPIO按键的短按与长按识别。本文介绍一种高效、稳定、易懂的实现方式,适合快速集成到你的项目中。 本文将以Air8000核心板为例,分享如何使用GPIO控制预留的POWER_ON按键,…

日总结 12

今天下午体测,由于这周一才通知,加上平常我确实也不太运动,我选择晚上去跑一跑,至少得能坚持下来吧(白天都是满课),事实证明平时不运动确实不好,跑一会儿就开始气喘吁吁的,但晚上跑步也让我看到了平时看不到的…

2025年太阳能板趋势与智能选择指南

文章摘要 本文深入分析2025年太阳能板市场趋势,包括效率提升、成本变化和行业展望,并提供实用选择指南,帮助家庭和工业用户做出明智决策。基于权威数据,我们探讨太阳能板的环保优势、安装维护技巧,以及如何通过性…

JarvisIR

一、第一页 1、现实世界中的恶略天气表现出耦合的退化(雨天、雪天、雾天等等往往还伴随着雨滴、模糊、光晕等)。 2、不良天气图像复原方法主要有三种:任务专用法、一体化方法、整合多种专用模型。 1)任务专用法:针…

10/15

学习了有关统计系统的代码。

抖音麒麟福袋软件操作指南

抖音麒麟福袋软件操作指南第一步: 电脑安装比特浏览器 比特官网地址:https://www.bitbrowser.cn/?code=9b70975d 安装好之后打开注册,并且实名第二步:点击分组管理,创建一个自己的分组,点击确认第三步:创建浏览…

2025 印尼物流专线公司推荐榜:聚焦合规高效,深圳恒翔物流凭实力登榜

近年来,中国与印尼贸易往来持续升温,制造业外贸出口、跨境电商等领域的蓬勃发展,带动印尼物流专线需求大幅增长。海运、空运等专线服务已从外贸企业专属,逐步延伸至电商卖家、生产制造等多个群体。2025 年,随着中…

国金证券 QMT 云服务器上 重启后 无法自动登录,如何解决?

国金证券 QMT 云服务器上 重启后 无法自动登录,如何解决?2025-10-15 18:24 Kyle_Lee 阅读(0) 评论(0) 收藏 举报国金证券的QMT真恶心啊,有自动登录的勾选框, 也有倒计时但就是没有记住密码,不让登录, 非要…

人文创新研究:在意义的边界探寻新境

人文创新研究:在意义的边界探寻新境 ——声明Ai研究 引言 在人类文明演进进程中,人文创新作为一种独特的创新形态,承载着探索精神世界、重构意义系统的重要使命。与技术创新关注物质改造不同,人文创新的核心在于意…

平面图最小割与对偶图最短路 - 干

平面图 即所有边都不相交的图。 例:对偶图 将平面图中的面转为点,每条边连接其左右的两个面,一个朴素的例子:其对偶图为:对偶图最短路 所以对偶图与最小割有什么关系呢? 在最小割问题中,我们经常会遇到面对平面…

深入解析:Nodejs开发环境搭建

深入解析:Nodejs开发环境搭建pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco"…

项目管理:PERT/CPM

网络计划图 概念 表示整个项目的网络图,成为项目网络。描述一个项目需要三方面的信息:活动、次序、时间。通常有两类网络:用弧表示活动的项目网络(双代号法,AOA);用节点表示活动的项目网络(单代号法,AON)。 …

mysql版本升级 8.0.22升级到8.0.34

mysql版本升级 8.0.22升级到8.0.341.使用mysqldump全量备份所有数据库 输入mysqldump -uroot -p --all-databases > all_databases.sql 输入密码 查看当前所在目录是否产生all_databases.sql (因为是小版本升级所…

智能物联网的实时通信之钥——WebSocket

要实现设备间的无缝协同与实时反馈,离不开一个高效可靠的通信协议。WebSocket正是开启智能物联网实时交互之门的“钥匙”,它让数据流动不再等待,为智能家居、智慧城市等场景注入即时生命力。 一、WebSocket基础知识…

2025 苏州注册公司服务机构实用推荐:选择深度解析

2025 年上半年苏州新增市场主体达 8.2 万家,初创企业占比超 6 成,注册代理服务需求持续攀升。面对繁杂的市场选择,结合服务效率、政策适配、风险防控等核心维度,我们实测筛选出 5 家综合实力突出的机构,为创业者提…

可信AI研究获资助,10位博士生探索算法公平与隐私

某机构向宾夕法尼亚大学10名工程博士提供资助,支持其开展可信人工智能研究。研究重点包括算法公平性、隐私保护、可解释性及神经符号学习等技术方向,旨在构建安全可靠的人工智能系统。某机构资助10名工程博士生开展可…