我的博客
diff --git a/src/components/blog/id/ReadingProgress.tsx b/src/components/blog/id/ReadingProgress.tsx
index afb13d8..b450f86 100644
--- a/src/components/blog/id/ReadingProgress.tsx
+++ b/src/components/blog/id/ReadingProgress.tsx
@@ -25,11 +25,15 @@ export default function ReadingProgress() {
if (!isVisible) return null;
return (
-
+ <>
+ {width && (
+
+ )}
+ >
);
}
From ce42091f679b3145b150329a7c16c2bd4bebd124 Mon Sep 17 00:00:00 2001
From: zhuba-Ahhh <3477826311@qq.com>
Date: Tue, 27 Aug 2024 17:56:37 +0800
Subject: [PATCH 2/9] docs: :memo: content3
---
src/data/blogPosts.ts | 91 +----------------
src/data/ts/3.ts | 227 ++++++++++++++++++++++++++++++++++++++++++
src/data/ts/index.ts | 3 +-
3 files changed, 231 insertions(+), 90 deletions(-)
create mode 100644 src/data/ts/3.ts
diff --git a/src/data/blogPosts.ts b/src/data/blogPosts.ts
index a2fd62d..83d7d87 100644
--- a/src/data/blogPosts.ts
+++ b/src/data/blogPosts.ts
@@ -1,4 +1,4 @@
-import { content1, content2 } from "./ts";
+import { content1, content2, content3 } from "./ts";
export interface BlogPost {
id: number;
@@ -37,94 +37,7 @@ export const blogPosts: BlogPost[] = [
id: 3,
title: "CSS-in-JS解决方案对比",
excerpt: "比较流行的CSS-in-JS库的优缺点...",
- content: `
-# CSS-in-JS解决方案对比
-
-CSS-in-JS已成为现代前端开发中的重要工具。本文将对比分析几种流行的CSS-in-JS解决方案,包括styled-components、Emotion、CSS Modules等。我们将从性能、开发体验、维护性等多个角度进行评估,并提供每种方案的最佳使用场景。此外,我们还将探讨CSS-in-JS与传统CSS方法的区别,以及如何在大型项目中有效管理样式。
-
-## styled-components
-
-styled-components是最流行的CSS-in-JS库之一。它结合了CSS和JavaScript的优点,使得我们可以在React组件中定义样式。
-
-### 优点
-
-1. 简洁的语法
-2. 支持动态样式
-3. 自动生成唯一的类名
-4. 易于主题化
-5. 良好的开发体验
-
-### 缺点
-
-1. 运行时性能开销
-2. 学习曲线较陡
-3. 不支持CSS Modules的特性
-
-### 最佳使用场景
-
-styled-components适用于需要动态样式和主题化的项目,尤其是中小型项目。
-
-## Emotion
-
-Emotion是另一种流行的CSS-in-JS库,它提供了更灵活的API和更好的性能。
-
-### 优点
-
-1. 高性能
-2. 支持CSS Modules的特性
-3. 易于主题化
-4. 良好的开发体验
-
-### 缺点
-
-1. 学习曲线较陡
-2. 不支持动态样式
-
-### 最佳使用场景
-
-Emotion适用于需要高性能和CSS Modules特性的项目,尤其是大型项目。
-
-## CSS Modules
-
-CSS Modules是一种CSS-in-JS解决方案,它将CSS模块化,并将类名作为JavaScript对象导出。
-
-### 优点
-
-1. 简单易用
-2. 支持CSS Modules的特性
-3. 良好的开发体验
-
-### 缺点
-
-1. 不支持动态样式
-2. 不易于主题化
-3. 类名不是唯一的
-
-### 最佳使用场景
-
-CSS Modules适用于需要简单、可维护的样式解决方案的项目,尤其是小型项目。
-
-## CSS-in-JS与传统CSS的区别
-
-CSS-in-JS与传统CSS有一些重要的区别:
-
-1. 作用域隔离: CSS-in-JS可以确保样式只应用于特定的组件,而传统CSS需要手动管理类名和命名空间。
-2. 动态样式: CSS-in-JS可以根据组件的状态和属性动态生成样式,而传统CSS需要使用JavaScript来切换类名。
-3. 主题化: CSS-in-JS可以轻松地支持主题化,而传统CSS需要使用预处理器或后处理器来实现。
-
-## 在大型项目中管理样式
-
-在大型项目中,有效管理样式是一个重要的挑战。以下是一些建议:
-
-1. 使用CSS-in-JS库: CSS-in-JS库可以提供更好的作用域隔离和动态样式支持,从而简化样式管理。
-2. 使用主题化: 主题化可以使样式更易于维护和扩展,尤其是在多个项目或不同环境中。
-3. 使用CSS Modules: CSS Modules可以提供简单、可维护的样式解决方案,尤其是在小型项目中。
-4. 使用CSS-in-JS库的最佳实践: 每个CSS-in-JS库都有自己的最佳实践,例如styled-components的\`ThemeProvider\`和Emotion的\`css\`函数。
-
-## 结论
-
-CSS-in-JS是一种强大的工具,它可以提供更好的作用域隔离、动态样式支持和主题化。styled-components、Emotion和CSS Modules都是流行的解决方案,每种方案都有自己的优缺点和最佳使用场景。在选择CSS-in-JS库时,应该根据项目的需求和规模来权衡性能、开发体验和维护性。
- `,
+ content: content3,
date: "2024-03-25",
author: "王五",
tags: ["CSS-in-JS", "styled-components", "Emotion"],
diff --git a/src/data/ts/3.ts b/src/data/ts/3.ts
new file mode 100644
index 0000000..7d350be
--- /dev/null
+++ b/src/data/ts/3.ts
@@ -0,0 +1,227 @@
+export const content3 = `
+# CSS-in-JS解决方案对比
+
+CSS-in-JS已成为现代前端开发中的重要工具。本文将对比分析几种流行的CSS-in-JS解决方案,包括styled-components、Emotion、CSS Modules等。我们将从性能、开发体验、维护性等多个角度进行评估,并提供每种方案的最佳使用场景。此外,我们还将探讨CSS-in-JS与传统CSS方法的区别,以及如何在大型项目中有效管理样式。
+
+## styled-components
+
+styled-components是最流行的CSS-in-JS库之一。它结合了CSS和JavaScript的优点,使得我们可以在React组件中定义样式。
+
+### 示例代码
+
+\`\`\`jsx
+import styled from 'styled-components';
+
+const Button = styled.button\`
+ background-color: \${props => props.primary ? 'blue' : 'white'};
+ color: \${props => props.primary ? 'white' : 'blue'};
+ font-size: 1em;
+ margin: 1em;
+ padding: 0.25em 1em;
+ border: 2px solid blue;
+ border-radius: 3px;
+\`;
+
+function App() {
+ return (
+
+
+
+
+ );
+}
+\`\`\`
+
+### 优点
+
+1. 简洁的语法
+2. 支持动态样式
+3. 自动生成唯一的类名
+4. 易于主题化
+5. 良好的开发体验
+
+### 缺点
+
+1. 运行时性能开销
+2. 学习曲线较陡
+3. 不支持CSS Modules的特性
+
+### 最佳使用场景
+
+styled-components适用于需要动态样式和主题化的项目,尤其是中小型项目。
+
+## Emotion
+
+Emotion是另一种流行的CSS-in-JS库,它提供了更灵活的API和更好的性能。
+
+### 示例代码
+
+\`\`\`jsx
+/** @jsxImportSource @emotion/react */
+import { css } from '@emotion/react';
+
+const buttonStyle = css\`
+ background-color: hotpink;
+ &:hover {
+ color: white;
+ }
+\`;
+
+function EmotionButton() {
+ return
;
+}
+\`\`\`
+
+### 优点
+
+1. 高性能
+2. 支持CSS Modules的特性
+3. 易于主题化
+4. 良好的开发体验
+
+### 缺点
+
+1. 学习曲线较陡
+2. 不支持动态样式
+
+### 最佳使用场景
+
+Emotion适用于需要高性能和CSS Modules特性的项目,尤其是大型项目。
+
+## CSS Modules
+
+CSS Modules是一种CSS-in-JS解决方案,它将CSS模块化,并将类名作为JavaScript对象导出。
+
+### 示例代码
+
+\`\`\`css
+/* Button.module.css */
+.button {
+ background-color: blue;
+ color: white;
+ padding: 10px 20px;
+ border: none;
+ border-radius: 5px;
+}
+\`\`\`
+
+\`\`\`jsx
+import React from 'react';
+import styles from './Button.module.css';
+
+function Button() {
+ return
;
+}
+\`\`\`
+
+### 优点
+
+1. 简单易用
+2. 支持CSS Modules的特性
+3. 良好的开发体验
+
+### 缺点
+
+1. 不支持动态样式
+2. 不易于主题化
+3. 类名不是唯一的
+
+### 最佳使用场景
+
+CSS Modules适用于需要简单、可维护的样式解决方案的项目,尤其是小型项目。
+
+## 其他值得关注的CSS-in-JS解决方案
+
+### JSS
+
+JSS是一个强大的CSS-in-JS工具,它允许你使用JavaScript来描述样式。
+
+#### 优点
+- 高度可定制
+- 支持插件系统
+- 良好的性能
+
+#### 缺点
+- 学习曲线较陡
+- 社区相对较小
+
+### Linaria
+
+Linaria是一个零运行时CSS-in-JS库,它在构建时将样式提取到CSS文件中。
+
+#### 优点
+- 零运行时开销
+- 支持静态提取
+- 类型安全
+
+#### 缺点
+- 不支持某些动态样式
+- 工具链集成可能复杂
+
+## CSS-in-JS与传统CSS的区别
+
+
+CSS-in-JS与传统CSS有一些重要的区别:
+
+1. 作用域隔离: CSS-in-JS可以确保样式只应用于特定的组件,而传统CSS需要手动管理类名和命名空间。
+2. 动态样式: CSS-in-JS可以根据组件的状态和属性动态生成样式,而传统CSS需要使用JavaScript来切换类名。
+3. 主题化: CSS-in-JS可以轻松地支持主题化,而传统CSS需要使用预处理器或后处理器来实现。
+
+## 在大型项目中管理样式
+
+在大型项目中,有效管理样式是一个重要的挑战。以下是一些建议:
+
+1. 使用CSS-in-JS库: CSS-in-JS库可以提供更好的作用域隔离和动态样式支持,从而简化样式管理。
+2. 使用主题化: 主题化可以使样式更易于维护和扩展,尤其是在多个项目或不同环境中。
+3. 使用CSS Modules: CSS Modules可以提供简单、可维护的样式解决方案,尤其是在小型项目中。
+4. 使用CSS-in-JS库的最佳实践: 每个CSS-in-JS库都有自己的最佳实践,例如styled-components的\`ThemeProvider\`和Emotion的\`css\`函数。
+5. 建立样式指南: 创建一个详细的样式指南,包括颜色、字体、间距等规范,以确保整个项目的一致性。
+6. 组件化: 将常用的样式封装成可重用的组件,减少重复代码。
+7. 性能优化: 使用工具如stylelint来检查和优化CSS,避免不必要的样式规则。
+
+### 示例: 使用主题化
+
+\`\`\`jsx
+import { ThemeProvider, createGlobalStyle } from 'styled-components';
+
+const theme = {
+ colors: {
+ primary: '#0070f3',
+ secondary: '#ff4081',
+ },
+ fonts: {
+ main: 'Arial, sans-serif',
+ },
+};
+
+const GlobalStyle = createGlobalStyle\`
+ body {
+ font-family: \${props => props.theme.fonts.main};
+ color: \${props => props.theme.colors.primary};
+ }
+\`;
+
+function App() {
+ return (
+
+
+ {/* 应用的其余部分 */}
+
+ );
+}
+\`\`\`
+
+## 选择合适的CSS-in-JS解决方案
+
+在选择CSS-in-JS解决方案时,需要考虑以下因素:
+
+1. 项目规模: 大型项目可能更适合使用Emotion或JSS等性能更好的解决方案。
+2. 团队经验: 考虑团队成员对不同解决方案的熟悉程度。
+3. 性能需求: 如果运行时性能至关重要,可以考虑Linaria等零运行时解决方案。
+4. 开发体验: 选择能提供良好开发体验和调试工具的解决方案。
+5. 生态系统: 考虑解决方案的社区支持和可用的工具/插件。
+
+## 结论
+
+CSS-in-JS是一种强大的工具,它可以提供更好的作用域隔离、动态样式支持和主题化。styled-components、Emotion、CSS Modules以及其他解决方案如JSS和Linaria都有各自的优缺点和适用场景。在选择CSS-in-JS库时,应该根据项目的需求、规模、团队经验和性能要求来权衡。无论选择哪种解决方案,建立良好的样式管理实践都是确保项目长期可维护性的关键。
+`;
diff --git a/src/data/ts/index.ts b/src/data/ts/index.ts
index 062386e..1895ba5 100644
--- a/src/data/ts/index.ts
+++ b/src/data/ts/index.ts
@@ -1,2 +1,3 @@
export * from "./1";
-export * from "./2";
\ No newline at end of file
+export * from "./2";
+export * from "./3";
From 5f618f23d8930bf866c44bd7610d1951d27a2bd7 Mon Sep 17 00:00:00 2001
From: zhuba-Ahhh <3477826311@qq.com>
Date: Tue, 27 Aug 2024 19:45:51 +0800
Subject: [PATCH 3/9] feat: :sparkles: headings
---
src/data/blogPosts.ts | 97 +------------------------
src/data/ts/4.ts | 153 +++++++++++++++++++++++++++++++++++++++
src/data/ts/index.ts | 1 +
src/utils/blogHelpers.ts | 16 +++-
4 files changed, 170 insertions(+), 97 deletions(-)
create mode 100644 src/data/ts/4.ts
diff --git a/src/data/blogPosts.ts b/src/data/blogPosts.ts
index 83d7d87..ad8d093 100644
--- a/src/data/blogPosts.ts
+++ b/src/data/blogPosts.ts
@@ -1,4 +1,4 @@
-import { content1, content2, content3 } from "./ts";
+import { content1, content2, content3, content4 } from "./ts";
export interface BlogPost {
id: number;
@@ -46,100 +46,7 @@ export const blogPosts: BlogPost[] = [
id: 4,
title: "TypeScript高级类型技巧",
excerpt: "掌握TypeScript中的高级类型用法...",
- content: `
-# TypeScript高级类型技巧
-
-TypeScript的类型系统非常强大,但也有一定的学习曲线。本文将深入探讨TypeScript中的高级类型技巧,包括条件类型、映射类型、联合类型和交叉类型等。我们将通过实际子展这些高级类型的应用,如何使用它们来创建更灵活、更安全的代码。同时,我们还将讨论TypeScript的类型推断机制,以及如何编写和使用自定义类型守卫。
-
-## 条件类型
-
-条件类型允许我们根据条件选择不同的类型。它的语法如下:
-
-\`\`\`
-type SomeType
= T extends SomeCondition ? TrueType : FalseType;
-\`\`\`
-
-例如,我们可以使用条件类型来创建一个\`Nullable\`类型:
-
-\`\`\`
-type Nullable = T extends null | undefined ? T : T & { notNull: true };
-\`\`\`
-
-## 映射类型
-
-映射类型允许我们对现有类型的每个属性进行转换。它的语法如下:
-
-\`\`\`
-type MappedType = {
- [P in keyof T]: TransformedType;
-};
-\`\`\`
-
-例如,我们可以使用映射类型来创建一个\`Readonly\`类型:
-
-\`\`\`
-type Readonly = {
- readonly [P in keyof T]: T[P];
-};
-\`\`\`
-
-## 联合类型和交叉类型
-
-联合类型允许我们表示多个类型中的任意一个。它的语法如下:
-
-\`\`\`
-type UnionType = Type1 | Type2 | Type3;
-\`\`\`
-
-交叉类型允许我们组合多个类型的属性。它的语法如下:
-
-\`\`\`
-type IntersectionType = Type1 & Type2 & Type3;
-\`\`\`
-
-例如,我们可以使用交叉类型来创建一个\`WithRequired\`类型:
-
-\`\`\`
-type WithRequired = T & { [P in K]-?: T[P] };
-\`\`\`
-
-## 类型推断
-
-TypeScript的类型推断机制可以自动推断变量的类型。它基于以下规则:
-
-1. 如果有明确的类型注释,则使用该类型
-2. 如果没有类型注释,则从初始化表达式推断类型
-3. 如果初始化表达式是函数调用,则使用函数返回类型
-
-例如,以下代码中的\`x\`和\`y\`都会被推断为\`number\`类型:
-
-\`\`\`
-let x = 10;
-let y = x * 2;
-\`\`\`
-
-## 自定义类型守卫
-
-自定义类型守卫允许我们在运行时检查类型。它的语法如下:
-
-\`\`\`
-function isTypeGuard(value: any): value is Type {
- // 检查类型
-}
-\`\`\`
-
-例如,我们可以使用自定义类型守卫来检查一个值是否是\`string\`类型:
-
-\`\`\`
-function isString(value: any): value is string {
- return typeof value === 'string';
-}
-\`\`\`
-
-## 结论
-
-TypeScript的高级类型技巧可以帮助我们创建更灵活、更安全的代码。通过掌握条件类型、映射类型、联合类型和交叉类型等高级类型,我们可以更好地表达复杂的类型关系。同时,通过理解TypeScript的类型推断机制和自定义类型守卫,我们可以更好地控制类型检查。
- `,
+ content: content4,
date: "2024-03-30",
author: "赵六",
tags: ["TypeScript", "类型系统", "前端开发"],
diff --git a/src/data/ts/4.ts b/src/data/ts/4.ts
new file mode 100644
index 0000000..5743ef1
--- /dev/null
+++ b/src/data/ts/4.ts
@@ -0,0 +1,153 @@
+export const content4 = `# TypeScript高级类型技巧
+
+TypeScript的类型系统非常强大,但也有一定的学习曲线。本文将深入探讨TypeScript中的高级类型技巧,包括条件类型、映射类型、联合类型和交叉类型等。我们将通过实际子展这些高级类型的应用,如何使用它们来创建更灵活、更安全的代码。同时,我们还将讨论TypeScript的类型推断机制,以及如何编写和使用自定义类型守卫。
+
+## 条件类型
+
+条件类型允许我们根据条件选择不同的类型。它的语法如下:
+
+\`\`\`
+type SomeType = T extends SomeCondition ? TrueType : FalseType;
+\`\`\`
+
+例如,我们可以使用条件类型来创建一个\`Nullable\`类型:
+
+\`\`\`
+type Nullable = T extends null | undefined ? T : T & { notNull: true };
+\`\`\`
+
+## 映射类型
+
+映射类型允许我们对现有类型的每个属性进行转换。它的语法如下:
+
+\`\`\`
+type MappedType = {
+ [P in keyof T]: TransformedType;
+};
+\`\`\`
+
+例如,我们可以使用映射类型来创建一个\`Readonly\`类型:
+
+\`\`\`
+type Readonly = {
+ readonly [P in keyof T]: T[P];
+};
+\`\`\`
+
+## 联合类型和交叉类型
+
+联合类型允许我们表示多个类型中的任意一个。它的语法如下:
+
+\`\`\`
+type UnionType = Type1 | Type2 | Type3;
+\`\`\`
+
+交叉类型允许我们组合多个类型的属性。它的语法如下:
+
+\`\`\`
+type IntersectionType = Type1 & Type2 & Type3;
+\`\`\`
+
+例如,我们可以使用交叉类型来创建一个\`WithRequired\`类型:
+
+\`\`\`
+type WithRequired = T & { [P in K]-?: T[P] };
+\`\`\`
+
+## 类型推断
+
+TypeScript的类型推断机制可以自动推断变量的类型。它基于以下规则:
+
+1. 如果有明确的类型注释,则使用该类型
+2. 如果没有类型注释,则从初始化表达式推断类型
+3. 如果初始化表达式是函数调用,则使用函数返回类型
+
+例如,以下代码中的\`x\`和\`y\`都会被推断为\`number\`类型:
+
+\`\`\`
+let x = 10;
+let y = x * 2;
+\`\`\`
+
+## 自定义类型守卫
+
+自定义类型守卫允许我们在运行时检查类型。它的语法如下:
+
+\`\`\`
+function isTypeGuard(value: any): value is Type {
+ // 检查类型
+}
+\`\`\`
+
+例如,我们可以使用自定义类型守卫来检查一个值是否是\`string\`类型:
+
+\`\`\`
+function isString(value: any): value is string {
+ return typeof value === 'string';
+}
+\`\`\`
+
+## 泛型约束
+
+泛型约束允许我们限制泛型类型参数可以接受的类型。它的语法如下:
+
+\`\`\`typescript
+interface WithLength {
+ length: number;
+}
+
+function logLength(arg: T): T {
+ console.log(arg.length);
+ return arg;
+}
+\`\`\`
+
+这个例子中,我们限制了泛型类型\`T\`必须包含\`length\`属性。
+
+## 索引类型查询操作符
+
+索引类型查询操作符\`keyof\`可以获取一个类型的所有属性名。例如:
+
+\`\`\`typescript
+interface Person {
+ name: string;
+ age: number;
+}
+
+type PersonKeys = keyof Person; // "name" | "age"
+\`\`\`
+
+## 类型别名与接口
+
+类型别名和接口都可以用来定义自定义类型,但它们有一些细微的区别:
+
+\`\`\`typescript
+// 类型别名
+type Point = {
+ x: number;
+ y: number;
+};
+
+// 接口
+interface Point {
+ x: number;
+ y: number;
+}
+\`\`\`
+
+类型别名可以表示任何类型,而接口只能表示对象类型。接口可以被类实现和继承,而类型别名不行。
+
+## 字面量类型
+
+字面量类型允许我们指定一个值作为类型:
+
+\`\`\`typescript
+type Direction = "north" | "south" | "east" | "west";
+let myDirection: Direction = "north"; // 有效
+myDirection = "northeast"; // 错误
+\`\`\`
+
+## 结论
+
+通过掌握这些高级类型技巧,我们可以更精确地控制类型,提高代码的可读性和可维护性。TypeScript的类型系统为我们提供了强大的工具,让我们能够在编译时捕获更多潜在的错误,同时也使得代码更加自文档化。持续学习和实践这些高级特性,将帮助我们成为更优秀的TypeScript开发者。
+`;
diff --git a/src/data/ts/index.ts b/src/data/ts/index.ts
index 1895ba5..796faf7 100644
--- a/src/data/ts/index.ts
+++ b/src/data/ts/index.ts
@@ -1,3 +1,4 @@
export * from "./1";
export * from "./2";
export * from "./3";
+export * from "./4";
diff --git a/src/utils/blogHelpers.ts b/src/utils/blogHelpers.ts
index 7b8ccdc..ce1c1e9 100644
--- a/src/utils/blogHelpers.ts
+++ b/src/utils/blogHelpers.ts
@@ -3,13 +3,25 @@ import { useMemo } from "react";
export function extractHeadings(content: string) {
const headingRegex = /^(#{1,3})\s+(.+)$/gm;
const headings = [];
+ const slugCounts: Record = {};
let match;
while ((match = headingRegex.exec(content)) !== null) {
+ const text = match[2];
+ let slug = text.toLowerCase().replace(/\s+/g, "-");
+
+ // 检查slug是否已存在,如果存在,则添加数字
+ if (slug in slugCounts) {
+ slugCounts[slug]++;
+ slug = `${slug}-${slugCounts[slug]}`;
+ } else {
+ slugCounts[slug] = 0;
+ }
+
headings.push({
level: match[1].length,
- text: match[2],
- slug: `${match[2].toLowerCase().replace(/\s+/g, "-")}`,
+ text: text,
+ slug: slug,
});
}
From 1f1d76066fa5993981ab49873035d85707b4df6e Mon Sep 17 00:00:00 2001
From: zhuba-Ahhh <3477826311@qq.com>
Date: Tue, 27 Aug 2024 20:05:41 +0800
Subject: [PATCH 4/9] chore: :hammer: content5
---
src/data/blogPosts.ts | 61 +---------
src/data/ts/5.ts | 262 ++++++++++++++++++++++++++++++++++++++++++
src/data/ts/index.ts | 1 +
3 files changed, 265 insertions(+), 59 deletions(-)
create mode 100644 src/data/ts/5.ts
diff --git a/src/data/blogPosts.ts b/src/data/blogPosts.ts
index ad8d093..cb4f4ad 100644
--- a/src/data/blogPosts.ts
+++ b/src/data/blogPosts.ts
@@ -1,4 +1,4 @@
-import { content1, content2, content3, content4 } from "./ts";
+import { content1, content2, content3, content4, content5 } from "./ts";
export interface BlogPost {
id: number;
@@ -55,64 +55,7 @@ export const blogPosts: BlogPost[] = [
id: 5,
title: "深入理解JavaScript异步编程",
excerpt: "探索JavaScript中的异步编程模式和最佳实践...",
- content: `
-# JavaScript异步编程深度解析
-
-JavaScript的异步编程是前端开发中的重要概念。本文将深入探讨各种异步编程模式及其应用。
-
-## 回调函数
-
-回调函数是最基本的异步编程方式:
-
-\`\`\`javascript
-function fetchData(callback) {
- setTimeout(() => {
- callback('Data fetched');
- }, 1000);
-}
-
-fetchData((result) => {
- console.log(result);
-});
-\`\`\`
-
-## Promise
-
-Promise提供了更优雅的异步处理方式:
-
-\`\`\`javascript
-function fetchData() {
- return new Promise((resolve, reject) => {
- setTimeout(() => {
- resolve('Data fetched');
- }, 1000);
- });
-}
-
-fetchData()
- .then(result => console.log(result))
- .catch(error => console.error(error));
-\`\`\`
-
-## Async/Await
-
-Async/Await是基于Promise的语法糖,使异步代码更易读:
-
-\`\`\`javascript
-async function getData() {
- try {
- const result = await fetchData();
- console.log(result);
- } catch (error) {
- console.error(error);
- }
-}
-
-getData();
-\`\`\`
-
-通过掌握这些异步编程模式,我们可以更好地处理复杂的异步操作,提高代码的可读性和可维护性。
- `,
+ content: content5,
date: "2024-04-05",
author: "陈七",
tags: ["JavaScript", "异步编程", "Promise", "Async/Await"],
diff --git a/src/data/ts/5.ts b/src/data/ts/5.ts
new file mode 100644
index 0000000..c97a08b
--- /dev/null
+++ b/src/data/ts/5.ts
@@ -0,0 +1,262 @@
+export const content5 = `
+# JavaScript异步编程深度解析
+
+JavaScript的异步编程是前端开发中的核心概念,对于构建高性能、响应迅速的web应用至关重要。本文将深入探讨各种异步编程模式,分析它们的工作原理、优缺点以及实际应用场景。
+
+## 1. 回调函数
+
+回调函数是最基本也是最古老的异步编程方式。它的核心思想是将一个函数作为参数传递给另一个函数,在异步操作完成后执行。
+
+### 基本示例
+
+\`\`\`javascript
+function fetchData(callback) {
+ setTimeout(() => {
+ callback('数据已获取');
+ }, 1000);
+}
+
+fetchData((result) => {
+ console.log(result);
+});
+\`\`\`
+
+### 深入分析
+
+回调函数的工作原理是基于JavaScript的事件循环机制。当异步操作完成时,回调函数会被添加到任务队列中,等待执行。
+
+### 优点
+- 简单直观,易于理解
+- 广泛支持,兼容性好
+- 灵活性高,可以轻松处理各种异步场景
+
+### 缺点
+- 容易陷入回调地狱,导致代码可读性差
+- 错误处理复杂,需要在每个回调中单独处理错误
+- 不易进行并行操作和流程控制
+- 代码结构不清晰,难以维护
+
+### 回调地狱示例
+
+\`\`\`javascript
+fetchUserData(userId, (userData) => {
+ fetchUserPosts(userData.id, (posts) => {
+ fetchPostComments(posts[0].id, (comments) => {
+ // 嵌套层级过深,难以阅读和维护
+ });
+ });
+});
+\`\`\`
+
+## 2. Promise
+
+Promise是ES6引入的一种更先进的异步编程方式,它代表一个异步操作的最终完成或失败。Promise提供了更优雅的异步处理方式,支持链式调用。
+
+### 基本示例
+
+\`\`\`javascript
+function fetchData() {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ resolve('数据已获取');
+ }, 1000);
+ });
+}
+
+fetchData()
+ .then(result => console.log(result))
+ .catch(error => console.error(error));
+\`\`\`
+
+### 深入分析
+
+Promise有三种状态pending(进行中)、fulfilled(已成功)和rejected(已失败)。一旦状态改变,就不会再变。这种状态机制使得异步操作的管理变得更加可控。
+
+### 优点
+- 链式调用,有效避免回调地狱
+- 统一的错误处理机制,使用.catch()捕获错误
+- 支持并行操作(Promise.all)和竞争操作(Promise.race)
+- 更好的异步流程控制
+
+### 缺点
+- 无法取消进行中的Promise
+- 单一值传递限制,每个Promise只能传递一个值
+- 对于复杂的异步流程,代码可能仍然显得冗长
+
+### 高级用法
+
+\`\`\`javascript
+// 并行操作
+Promise.all([fetchData1(), fetchData2(), fetchData3()])
+ .then(([result1, result2, result3]) => {
+ console.log(result1, result2, result3);
+ });
+
+// 竞争操作
+Promise.race([fetchData1(), fetchData2(), fetchData3()])
+ .then(fastestResult => {
+ console.log(fastestResult);
+ });
+
+// Promise链
+fetchUserData(userId)
+ .then(userData => fetchUserPosts(userData.id))
+ .then(posts => fetchPostComments(posts[0].id))
+ .then(comments => {
+ // 处理评论
+ })
+ .catch(error => {
+ // 统一错误处理
+ });
+\`\`\`
+
+## 3. Async/Await
+
+Async/Await是ES2017引入的基于Promise的语法糖,它使异步代码的结构和写法更接近于同步代码,大大提高了代码的可读性。
+
+### 基本示例
+
+\`\`\`javascript
+async function getData() {
+ try {
+ const result = await fetchData();
+ console.log(result);
+ } catch (error) {
+ console.error(error);
+ }
+}
+
+getData();
+\`\`\`
+
+### 深入分析
+
+Async/Await在底层仍然使用Promise,但它提供了一种更直观的方式来处理异步操作。async函数总是返回一个Promise,而await关键字可以暂停async函数的执行,等待Promise解决。
+
+### 优点
+- 代码结构清晰,读起来像同步代码,易读易维护
+- 更好的错误处理机制,可以使用try/catch捕获同步和异步错误
+- 方便调试,可以像调试同步代码一样设置断点
+- 减少了Promise的模板代码
+
+### 缺点
+- 如果不当使用await,可能导致性能问题(阻塞执行)
+- 需要注意并行操作的处理,避免不必要的串行等待
+
+### 高级用法
+
+\`\`\`javascript
+// 并行操作
+async function fetchAllData() {
+ const [result1, result2, result3] = await Promise.all([
+ fetchData1(),
+ fetchData2(),
+ fetchData3()
+ ]);
+ console.log(result1, result2, result3);
+}
+
+// 错误重试
+async function fetchWithRetry(url, retries = 3) {
+ for (let i = 0; i < retries; i++) {
+ try {
+ return await fetch(url);
+ } catch (error) {
+ if (i === retries - 1) throw error;
+ console.log(\`重试第\${i + 1}次\`);
+ }
+ }
+}
+\`\`\`
+
+## 4. 异步迭代器和生成器
+
+ES2018引入的异步迭代器和生成器为处理异步数据流提供了新的方式,特别适合处理大量数据或流式数据。
+
+### 基本示例
+
+\`\`\`javascript
+async function* asyncGenerator() {
+ yield await fetchData1();
+ yield await fetchData2();
+ yield await fetchData3();
+}
+
+(async () => {
+ for await (const data of asyncGenerator()) {
+ console.log(data);
+ }
+})();
+\`\`\`
+
+### 深入分析
+
+异步迭代器允许我们用for-await-of循环遍历异步数据源。异步生成器则可以用来创建异步数据流,每次yield一个Promise。
+
+### 优点
+- 适合处理大量异步数据或流式数据
+- 可以按需生成和消费数据,节省内存
+- 提供了一种统一的方式来处理同步和异步迭代
+
+### 缺点
+- 概念相对复杂,学习曲线较陡
+- 浏览器支持可能不够广泛,需要考虑兼容性
+
+### 高级用法
+
+\`\`\`javascript
+// 异步数据分页
+async function* fetchPaginatedData(url) {
+ let nextPage = url;
+ while (nextPage) {
+ const response = await fetch(nextPage);
+ const data = await response.json();
+ yield data.items;
+ nextPage = data.nextPage;
+ }
+}
+
+// 使用
+(async () => {
+ for await (const items of fetchPaginatedData('https//api.example.com/data')) {
+ for (const item of items) {
+ console.log(item);
+ }
+ }
+})();
+\`\`\`
+
+## 5. 实际应用示例
+
+结合Fetch API使用Async/Await,展示了如何在实际项目中应用异步编程
+
+\`\`\`javascript
+async function fetchUserData(userId) {
+ try {
+ const response = await fetch(\`https//api.example.com/users/\${userId}\`);
+ if (!response.ok) {
+ throw new Error('网络响应不正常');
+ }
+ const userData = await response.json();
+ console.log(userData);
+ } catch (error) {
+ console.error('获取用户数据失败', error);
+ }
+}
+
+fetchUserData(123);
+\`\`\`
+
+## 总结
+
+通过深入理解和掌握这些异步编程模式,我们可以
+1. 更好地处理复杂的异步操作,提高应用性能
+2. 显著提高代码的可读性和可维护性
+3. 有效避免回调地狱,使代码结构更清晰
+4. 优雅地处理错误和异常情况,提高应用的稳定性
+5. 灵活应对不同的异步场景需求,如并发操作、数据流处理等
+
+在实际开发中,我们应该根据具体需求和场景选择最适合的异步处理方式。通常,现代JavaScript开发中更倾向于使用Promise和Async/Await,因为它们提供了更好的可读性和错误处理能力。然而,理解回调函数的工作原理仍然很重要,因为许多旧的API和库仍在使用回调。
+
+异步编程是一个不断发展的领域,未来可能会出现更多新的模式和API。保持学习和实践,不断更新知识,对于成为一个优秀的JavaScript开发者至关重要。
+`;
diff --git a/src/data/ts/index.ts b/src/data/ts/index.ts
index 796faf7..139b832 100644
--- a/src/data/ts/index.ts
+++ b/src/data/ts/index.ts
@@ -2,3 +2,4 @@ export * from "./1";
export * from "./2";
export * from "./3";
export * from "./4";
+export * from "./5";
From bab6b1fab8fcc17a5ba8534d9aefecbfa2eeda64 Mon Sep 17 00:00:00 2001
From: zhuba-Ahhh <3477826311@qq.com>
Date: Tue, 27 Aug 2024 20:10:55 +0800
Subject: [PATCH 5/9] docs: :memo: content6
---
src/data/blogPosts.ts | 67 ++--------
src/data/ts/6.ts | 283 ++++++++++++++++++++++++++++++++++++++++++
src/data/ts/copy.ts | 1 +
src/data/ts/index.ts | 1 +
4 files changed, 294 insertions(+), 58 deletions(-)
create mode 100644 src/data/ts/6.ts
create mode 100644 src/data/ts/copy.ts
diff --git a/src/data/blogPosts.ts b/src/data/blogPosts.ts
index cb4f4ad..e759310 100644
--- a/src/data/blogPosts.ts
+++ b/src/data/blogPosts.ts
@@ -1,4 +1,11 @@
-import { content1, content2, content3, content4, content5 } from "./ts";
+import {
+ content1,
+ content2,
+ content3,
+ content4,
+ content5,
+ content6,
+} from "./ts";
export interface BlogPost {
id: number;
@@ -64,63 +71,7 @@ export const blogPosts: BlogPost[] = [
id: 6,
title: "React性能优化实战指南",
excerpt: "学习React应用的高级性能优化技巧...",
- content: `
-# React性能优化实战指南
-
-在构建大型React应用时,性能优化至关重要。本文将介绍一些实用的React性能优化技巧。
-
-## 使用React.memo
-
-React.memo可以帮助我们避免不必要的重渲染:
-
-\`\`\`jsx
-const MyComponent = React.memo(function MyComponent(props) {
- /* 渲染使用到的props */
-});
-\`\`\`
-
-## 使用useMemo和useCallback
-
-useMemo和useCallback可以帮助我们缓存计算结果和回调函数:
-
-\`\`\`jsx
-const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
-
-const memoizedCallback = useCallback(
- () => {
- doSomething(a, b);
- },
- [a, b],
-);
-\`\`\`
-
-## 虚拟化长列表
-
-对于长列表,我们可以使用虚拟化技术来提高性能:
-
-\`\`\`jsx
-import { FixedSizeList as List } from 'react-window';
-
-function Row({ index, style }) {
- return Row {index}
;
-}
-
-function Example() {
- return (
-
- {Row}
-
- );
-}
-\`\`\`
-
-通过应用这些优化技巧,我们可以显著提升React应用的性能,为用户提供更流畅的体验。
- `,
+ content: content6,
date: "2024-04-10",
author: "林八",
tags: ["React", "性能优化", "虚拟列表"],
diff --git a/src/data/ts/6.ts b/src/data/ts/6.ts
new file mode 100644
index 0000000..46f7fee
--- /dev/null
+++ b/src/data/ts/6.ts
@@ -0,0 +1,283 @@
+export const content6 = `
+# React性能优化实战指南
+
+在构建大型React应用时,性能优化至关重要。本文将深入介绍一些实用的React性能优化技巧,帮助您的应用运行得更快、更流畅。
+
+## 1. 使用React.memo
+
+React.memo是一个高阶组件,可以帮助我们避免不必要的重渲染。它通过对比props来决定是否需要重新渲染组件。
+
+\`\`\`jsx
+const MyComponent = React.memo(function MyComponent(props) {
+ /* 渲染使用到的props */
+});
+\`\`\`
+
+使用React.memo的注意事项:
+- 只在props经常变化的组件上使用
+- 对于依赖复杂对象的组件,考虑自定义比较函数
+
+### 深入理解React.memo
+
+React.memo通过浅比较props来决定是否重新渲染。对于复杂的props,可以提供自定义的比较函数:
+
+\`\`\`jsx
+function areEqual(prevProps, nextProps) {
+ // 自定义比较逻辑
+ return prevProps.complexProp.id === nextProps.complexProp.id;
+}
+
+const MemoizedComponent = React.memo(MyComponent, areEqual);
+\`\`\`
+
+注意:过度使用React.memo可能导致代码复杂性增加,应权衡利弊。
+
+## 2. 使用useMemo和useCallback
+
+useMemo和useCallback是React提供的两个强大的Hook,用于优化性能。
+
+### useMemo
+
+useMemo用于缓存计算结果:
+
+\`\`\`jsx
+const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
+\`\`\`
+
+使用场景:
+- 昂贵的计算
+- 避免重复创建对象
+
+#### useMemo的高级用法
+
+useMemo还可以用于优化子组件的渲染:
+
+\`\`\`jsx
+function ParentComponent({ data }) {
+ const memoizedData = useMemo(() => processData(data), [data]);
+ return ;
+}
+\`\`\`
+
+### useCallback
+
+useCallback用于缓存回调函数:
+
+\`\`\`jsx
+const memoizedCallback = useCallback(
+ () => {
+ doSomething(a, b);
+ },
+ [a, b],
+);
+\`\`\`
+
+使用场景:
+- 传递给子组件的回调函数
+- 依赖项列表中使用的函数
+
+#### useCallback vs useMemo
+
+useCallback实际上是useMemo的一个特例:
+
+\`\`\`jsx
+useCallback(fn, deps) 等价于 useMemo(() => fn, deps)
+\`\`\`
+
+## 3. 虚拟化长列表
+
+对于长列表,使用虚拟化技术可以显著提高性能。react-window和react-virtualized是两个流行的库。
+
+使用react-window的例子:
+
+\`\`\`jsx
+import { FixedSizeList as List } from 'react-window';
+
+function Row({ index, style }) {
+ return Row {index}
;
+}
+
+function Example() {
+ return (
+
+ {Row}
+
+ );
+}
+\`\`\`
+
+虚拟化的优点:
+- 只渲染可见区域的项目
+- 大大减少DOM节点数量
+- 提高滚动性能
+
+### 动态高度列表
+
+对于项目高度不固定的列表,可以使用\`VariableSizeList\`:
+
+\`\`\`jsx
+import { VariableSizeList as List } from 'react-window';
+
+const getItemSize = index => {
+ // 根据索引返回项目高度
+ return index % 2 ? 50 : 80;
+};
+
+function Example() {
+ return (
+
+ {Row}
+
+ );
+}
+\`\`\`
+
+## 4. 使用React.lazy进行代码分割
+
+React.lazy允许您动态导入组件,实现代码分割:
+
+\`\`\`jsx
+const OtherComponent = React.lazy(() => import('./OtherComponent'));
+
+function MyComponent() {
+ return (
+ Loading... }>
+