vault backup: 2026-04-24 23:45:19
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
---
|
||||
tags: [前端, CSS, 基础]
|
||||
create time: 2026-04-24 18:41
|
||||
---
|
||||
|
||||
# CSS 基础
|
||||
|
||||
## 概述
|
||||
|
||||
CSS(Cascading Style Sheets)负责网页的视觉呈现。如果说 HTML 是骨架,CSS 就是皮肤和衣服。掌握 CSS 的核心是理解三个概念:**选择器**(选谁)、**盒模型**(有多大)、**布局**(怎么排)。
|
||||
|
||||
思考题:为什么 CSS 叫做"层叠"样式表?多个规则作用于同一个元素时,浏览器如何决定用哪一个?
|
||||
|
||||
## 正文
|
||||
|
||||
### 1. CSS 引入方式
|
||||
|
||||
```html
|
||||
<!-- 方式一:行内样式(不推荐) -->
|
||||
<p style="color: red; font-size: 16px;">红色文字</p>
|
||||
|
||||
<!-- 方式二:内部样式表 -->
|
||||
<style>
|
||||
p { color: blue; }
|
||||
</style>
|
||||
|
||||
<!-- 方式三:外部样式表(推荐) -->
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
```
|
||||
|
||||
### 2. 选择器优先级
|
||||
|
||||
```
|
||||
!important > 行内样式 > ID选择器 > 类选择器 > 标签选择器 > 通配符
|
||||
10000 1000 100 10 1 0
|
||||
```
|
||||
|
||||
```css
|
||||
/* 优先级实战 */
|
||||
div .item { color: red; } /* 0*1000 + 1*100 + 1*10 = 110 */
|
||||
div p.item { color: blue; } /* 0*1000 + 1*100 + 1*10 + 1*1 = 111 */
|
||||
#main .item { color: green; } /* 1*1000 + 0*100 + 1*10 = 1010 */
|
||||
```
|
||||
|
||||
> **提问:** 如果一个元素同时被 `.a { color: red }` 和 `#b { color: blue }` 选中,最终颜色是什么?为什么?
|
||||
|
||||
### 3. 盒模型(Box Model)
|
||||
|
||||
每个元素都是一个盒子,由四部分组成:
|
||||
|
||||
```mermaid
|
||||
block-beta
|
||||
columns 1
|
||||
margin["margin 外边距\n(透明,不影响盒子大小)"]
|
||||
border["border 边框"]
|
||||
padding["padding 内边距\n(盒子内部,影响背景色)"]
|
||||
content["content 内容区\n(实际文字/图片)"]
|
||||
```
|
||||
|
||||
```css
|
||||
/* 两种盒模型的区别 */
|
||||
.box-content-box {
|
||||
box-sizing: content-box; /* 默认:width = content 宽度 */
|
||||
}
|
||||
.box-border-box {
|
||||
box-sizing: border-box; /* 推荐:width = content + padding + border */
|
||||
}
|
||||
```
|
||||
|
||||
> **核心要点:** 实际开发中建议全局使用 `box-sizing: border-box`,避免尺寸计算混乱。
|
||||
|
||||
### 4. Flexbox 布局(一维布局首选)
|
||||
|
||||
```css
|
||||
.container {
|
||||
display: flex;
|
||||
justify-content: center; /* 主轴居中 */
|
||||
align-items: center; /* 交叉轴居中 */
|
||||
gap: 16px; /* 子元素间距 */
|
||||
}
|
||||
|
||||
.item {
|
||||
flex: 1; /* 等宽分配 */
|
||||
/* 或者 flex: 0 0 200px; 固定宽度 */
|
||||
}
|
||||
```
|
||||
|
||||
Flexbox 常用属性速查:
|
||||
|
||||
| 属性 | 作用 |
|
||||
|------|------|
|
||||
| `display: flex` | 启用 flex 布局 |
|
||||
| `justify-content` | 主轴对齐(center / space-between / space-around) |
|
||||
| `align-items` | 交叉轴对齐(center / flex-start / stretch) |
|
||||
| `flex-direction` | 主轴方向(row / column) |
|
||||
| `gap` | 子元素间距 |
|
||||
|
||||
> **提问:** 什么时候用 Flexbox,什么时候用 Grid?它们的本质区别是什么?
|
||||
|
||||
### 5. Grid 布局(二维布局神器)
|
||||
|
||||
```css
|
||||
.grid-container {
|
||||
display: grid;
|
||||
grid-template-columns: 200px 1fr 1fr; /* 三列:固定 + 自适应 */
|
||||
grid-template-rows: auto 1fr auto; /* 三行:自动 + 弹性 + 自动 */
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
/* 响应式网格 */
|
||||
.grid-responsive {
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
}
|
||||
```
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A["display: grid"] --> B["grid-template-columns\n定义列"]
|
||||
A --> C["grid-template-rows\n定义行"]
|
||||
A --> D["gap\n间距"]
|
||||
A --> E["justify/align\n对齐"]
|
||||
```
|
||||
|
||||
### 6. 响应式设计
|
||||
|
||||
```css
|
||||
/* 媒体查询:不同屏幕尺寸应用不同样式 */
|
||||
.container {
|
||||
width: 100%;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.container {
|
||||
padding: 0 10px;
|
||||
}
|
||||
.grid-layout {
|
||||
grid-template-columns: 1fr; /* 窄屏单列 */
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> **关键概念:** 移动端优先(Mobile First)是现代响应式设计的最佳实践——先写移动端样式,再用 `min-width` 媒体查询逐步增强。
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[HTML 基础]] — CSS 的搭档,HTML 提供结构,CSS 提供样式
|
||||
- [[JavaScript 基础]] — 通过 JS 动态修改 CSS,实现交互效果
|
||||
@@ -0,0 +1,126 @@
|
||||
---
|
||||
tags: [前端, HTML, 基础]
|
||||
create time: 2026-04-24 18:41
|
||||
---
|
||||
|
||||
# HTML 基础
|
||||
|
||||
## 概述
|
||||
|
||||
HTML(HyperText Markup Language)是构建网页的骨架。它不是一门编程语言,而是一种标记语言——用标签(tag)告诉浏览器"这里是一段标题"、"这里是一个按钮"、"这里是一张图片"。
|
||||
|
||||
思考题:为什么 HTML 被称为"标记语言"而不是"编程语言"?它有没有变量、循环或条件判断的能力?
|
||||
|
||||
## 正文
|
||||
|
||||
### 1. HTML 文档结构
|
||||
|
||||
一个标准的 HTML 文档包含以下核心部分:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html> <!-- 文档类型声明:告诉浏览器这是 HTML5 -->
|
||||
<html lang="zh-CN"> <!-- 根元素,lang 指定语言 -->
|
||||
<head> <!-- 元信息容器:不直接显示 -->
|
||||
<meta charset="UTF-8"> <!-- 字符编码 -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>页面标题</title> <!-- 浏览器标签页标题 -->
|
||||
</head>
|
||||
<body> <!-- 可见内容容器 -->
|
||||
<h1>Hello World</h1>
|
||||
<p>这是一段文字</p>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
### 2. 常用标签分类
|
||||
|
||||
**标题与段落:**
|
||||
|
||||
| 标签 | 用途 |
|
||||
|------|------|
|
||||
| `<h1>` ~ `<h6>` | 标题(h1 最大,h6 最小) |
|
||||
| `<p>` | 段落 |
|
||||
| `<br>` | 换行 |
|
||||
| `<hr>` | 水平线 |
|
||||
|
||||
**文本格式化:**
|
||||
|
||||
| 标签 | 用途 |
|
||||
|------|------|
|
||||
| `<strong>` | 加粗(语义:重要) |
|
||||
| `<em>` | 斜体(语义:强调) |
|
||||
| `<code>` | 代码 |
|
||||
| `<mark>` | 高亮 |
|
||||
|
||||
**链接与图片:**
|
||||
|
||||
```html
|
||||
<a href="https://example.com" target="_blank">打开新窗口</a> <!-- 外部链接 -->
|
||||
<img src="photo.jpg" alt="描述文字"> <!-- 图片(alt 必填) -->
|
||||
```
|
||||
|
||||
> **提问:** 为什么 `<img>` 标签的 `alt` 属性是必填的?它除了辅助功能外,还对 SEO(搜索引擎优化)有什么影响?
|
||||
|
||||
**列表:**
|
||||
|
||||
```html
|
||||
<!-- 无序列表 -->
|
||||
<ul>
|
||||
<li>第一项</li>
|
||||
<li>第二项</li>
|
||||
</ul>
|
||||
|
||||
<!-- 有序列表 -->
|
||||
<ol>
|
||||
<li>第一步</li>
|
||||
<li>第二步</li>
|
||||
</ol>
|
||||
```
|
||||
|
||||
### 3. 表单 — 用户交互的核心
|
||||
|
||||
```html
|
||||
<form action="/api/submit" method="POST">
|
||||
<label for="username">用户名:</label>
|
||||
<input type="text" id="username" name="username" required>
|
||||
|
||||
<label for="email">邮箱:</label>
|
||||
<input type="email" id="email" name="email" placeholder="example@mail.com">
|
||||
|
||||
<label for="password">密码:</label>
|
||||
<input type="password" id="password" name="password">
|
||||
|
||||
<label for="gender">性别:</label>
|
||||
<select id="gender" name="gender">
|
||||
<option value="">请选择</option>
|
||||
<option value="male">男</option>
|
||||
<option value="female">女</option>
|
||||
</select>
|
||||
|
||||
<button type="submit">提交</button>
|
||||
</form>
|
||||
```
|
||||
|
||||
> **思考:** `GET` 和 `POST` 方法有什么区别?为什么登录表单必须用 `POST` 而不是 `GET`?
|
||||
|
||||
### 4. 语义化标签 — HTML5 的新武器
|
||||
|
||||
```html
|
||||
<header> <!-- 页眉 -->
|
||||
<nav> <!-- 导航栏 -->
|
||||
<main> <!-- 主要内容 -->
|
||||
<section> <!-- 独立章节 -->
|
||||
<article> <!-- 独立文章 -->
|
||||
<aside> <!-- 侧边栏 -->
|
||||
<footer> <!-- 页脚 -->
|
||||
```
|
||||
|
||||
语义化的好处:
|
||||
- **SEO 友好**:搜索引擎更容易理解页面结构
|
||||
- **无障碍访问**:屏幕阅读器能更好地辅助视障用户
|
||||
- **代码可读性**:开发者一眼就能看懂结构
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[CSS 基础]] — 接下来学习如何用 CSS 美化 HTML
|
||||
- [[JavaScript 基础]] — 最后学习如何让页面动起来
|
||||
@@ -0,0 +1,165 @@
|
||||
---
|
||||
tags: [前端, JavaScript, 基础]
|
||||
create time: 2026-04-24 18:41
|
||||
---
|
||||
|
||||
# JavaScript 基础
|
||||
|
||||
## 概述
|
||||
|
||||
JavaScript 是前端唯一的专业编程语言。它让网页从静态内容变成动态交互:点击按钮弹出对话框、表单验证、数据异步加载、动画效果……所有这些都需要 JS。
|
||||
|
||||
思考题:JavaScript 是单线程语言,那它如何实现"异步"而不阻塞页面?
|
||||
|
||||
## 正文
|
||||
|
||||
### 1. 变量与数据类型
|
||||
|
||||
```javascript
|
||||
// 三种变量声明方式
|
||||
let name = "Alice"; // let:块级作用域,可重新赋值
|
||||
const age = 25; // const:块级作用域,不可重新赋值
|
||||
var old = 10; // var:函数作用域(老旧写法,尽量少用)
|
||||
|
||||
// JavaScript 的主要数据类型
|
||||
let text = "Hello"; // string
|
||||
let num = 42; // number
|
||||
let flag = true; // boolean
|
||||
let empty = null; // null:有意为空
|
||||
let notDefined; // undefined:未赋值
|
||||
let list = [1, 2, 3]; // array
|
||||
let person = { name: "Alice" }; // object
|
||||
```
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[JavaScript 数据类型] --> B[原始类型 Primitive]
|
||||
A --> C[引用类型 Reference]
|
||||
B --> D[string]
|
||||
B --> E[number]
|
||||
B --> F[boolean]
|
||||
B --> G[null]
|
||||
B --> H[undefined]
|
||||
B --> I[Symbol]
|
||||
B --> J[BigInt]
|
||||
C --> K[array]
|
||||
C --> L[object]
|
||||
C --> M[Function]
|
||||
```
|
||||
|
||||
> **提问:** `typeof null` 返回 `"object"` 是 JavaScript 的历史 bug 吗?为什么这个 bug 至今没有修复?
|
||||
|
||||
### 2. 函数
|
||||
|
||||
```javascript
|
||||
// 函数声明
|
||||
function add(a, b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
// 箭头函数(ES6+ 推荐)
|
||||
const multiply = (a, b) => a * b;
|
||||
|
||||
// 默认参数
|
||||
const greet = (name = "World") => `Hello, ${name}!`;
|
||||
|
||||
// 函数作为参数(高阶函数)
|
||||
const numbers = [1, 2, 3, 4, 5];
|
||||
const doubled = numbers.map(n => n * 2); // [2, 4, 6, 8, 10]
|
||||
const evens = numbers.filter(n => n % 2 === 0); // [2, 4]
|
||||
const sum = numbers.reduce((acc, n) => acc + n, 0); // 15
|
||||
```
|
||||
|
||||
> **核心概念:** map / filter / reduce 是函数式编程的核心三件套,也是 React 中处理数据的核心模式。
|
||||
|
||||
### 3. DOM 操作
|
||||
|
||||
```javascript
|
||||
// 获取元素
|
||||
const btn = document.getElementById("submit-btn");
|
||||
const items = document.querySelectorAll(".item");
|
||||
|
||||
// 修改内容
|
||||
btn.textContent = "点击我";
|
||||
btn.innerHTML = "<strong>加粗文字</strong>";
|
||||
|
||||
// 修改样式
|
||||
btn.style.backgroundColor = "blue";
|
||||
btn.classList.add("active"); // 添加 class
|
||||
btn.classList.toggle("hidden"); // 切换 class
|
||||
|
||||
// 创建元素
|
||||
const newDiv = document.createElement("div");
|
||||
newDiv.textContent = "动态创建的元素";
|
||||
document.body.appendChild(newDiv);
|
||||
|
||||
// 事件监听
|
||||
btn.addEventListener("click", () => {
|
||||
alert("按钮被点击了!");
|
||||
});
|
||||
```
|
||||
|
||||
### 4. 异步编程 — 前端最核心的难点
|
||||
|
||||
```javascript
|
||||
// 方式一:Promise
|
||||
fetch("https://api.example.com/users")
|
||||
.then(response => response.json())
|
||||
.then(data => console.log(data))
|
||||
.catch(error => console.error(error));
|
||||
|
||||
// 方式二:async/await(推荐,更直观)
|
||||
async function getUsers() {
|
||||
try {
|
||||
const response = await fetch("https://api.example.com/users");
|
||||
const data = await response.json();
|
||||
console.log(data);
|
||||
} catch (error) {
|
||||
console.error("请求失败:", error);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as 用户
|
||||
participant B as 浏览器
|
||||
participant S as 服务器
|
||||
U->>B: 点击按钮
|
||||
B->>B: 触发 async 函数
|
||||
B->>S: fetch 请求发送
|
||||
Note over B: 页面不卡顿!(非阻塞)
|
||||
S-->>B: 返回 JSON 数据
|
||||
B->>B: .then() / await 处理数据
|
||||
B->>U: 更新页面内容
|
||||
```
|
||||
|
||||
> **提问:** `Promise` 的三种状态(pending / fulfilled / rejected)是如何流转的?为什么 `async/await` 本质上是 Promise 的语法糖?
|
||||
|
||||
### 5. 作用域与闭包
|
||||
|
||||
```javascript
|
||||
// 作用域链
|
||||
function outer() {
|
||||
let count = 0; // 外层函数变量
|
||||
|
||||
return function() { // 内部函数"记住"了外层的 count
|
||||
count++;
|
||||
return count;
|
||||
};
|
||||
}
|
||||
|
||||
const counter = outer();
|
||||
console.log(counter()); // 1
|
||||
console.log(counter()); // 2
|
||||
console.log(counter()); // 3
|
||||
```
|
||||
|
||||
> **思考:** 闭包是 JS 中最强大的特性之一,但它也被广泛用于实现单例模式、数据隐藏和回调函数。你能想到闭包在真实项目中的哪些应用场景?
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[HTML 基础]] — JS 操作 HTML 的 DOM 树
|
||||
- [[CSS 基础]] — JS 动态修改 CSS 样式
|
||||
- [[TypeScript 基础]] — 给 JS 加上类型系统
|
||||
- [[30.areas/finance/Investment lessons/2024.Current trading lessons.md]]
|
||||
@@ -0,0 +1,66 @@
|
||||
---
|
||||
tags: [前端, 全栈, 学习路线]
|
||||
create time: 2026-04-24 18:41
|
||||
---
|
||||
|
||||
# 前端学习总览
|
||||
|
||||
## 概述
|
||||
|
||||
前端开发是用户与产品交互的第一触点。这个文件夹系统地梳理了从网页骨架(HTML)到样式(CSS),再到交互逻辑(JavaScript)和类型保障(TypeScript)的完整学习路径。
|
||||
|
||||
核心问题:为什么前端学习必须遵循 HTML → CSS → JS → TS 的顺序?如果跳过 CSS 直接写 React,会遇到什么问题?
|
||||
|
||||
## 学习路线图
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[HTML 基础] --> B[CSS 基础]
|
||||
B --> C[JavaScript 基础]
|
||||
C --> D[TypeScript 基础]
|
||||
D --> E[React 框架]
|
||||
E --> F[Vite / 构建工具]
|
||||
```
|
||||
|
||||
### 阶段一:网页骨架 — HTML
|
||||
|
||||
掌握 HTML 标签、文档结构、表单元素、语义化标签。这是所有前端知识的起点。
|
||||
|
||||
### 阶段二:网页样式 — CSS
|
||||
|
||||
掌握选择器优先级、盒模型、Flexbox 布局、Grid 布局、响应式设计。CSS 是前端最容易被低估的部分。
|
||||
|
||||
### 阶段三:交互逻辑 — JavaScript
|
||||
|
||||
掌握变量与数据类型、函数与作用域、DOM 操作、事件处理、异步编程(Promise / async-await)。JavaScript 是让页面"活起来"的语言。
|
||||
|
||||
### 阶段四:类型保障 — TypeScript
|
||||
|
||||
掌握类型注解、接口、泛型、联合类型、工具类型。TypeScript 是大型前端项目的工业标准。
|
||||
|
||||
### 阶段五:框架进阶 — React(已在 DEV/REACT/ 中)
|
||||
|
||||
在掌握 JS 和 TS 基础上,进入 React 组件化开发、状态管理、Hooks 体系。
|
||||
|
||||
### 阶段六:工程化 — Vite(已在 DEV/VITE/ 中)
|
||||
|
||||
学习构建工具、模块打包、开发服务器配置。
|
||||
|
||||
## 笔记索引
|
||||
|
||||
| 笔记 | 状态 | 说明 |
|
||||
|------|------|------|
|
||||
| [[HTML 基础]] | 基础 | HTML 标签、文档结构、表单 |
|
||||
| [[CSS 基础]] | 基础 | 选择器、盒模型、Flex、Grid |
|
||||
| [[JavaScript 基础]] | 基础 | 变量、函数、DOM操作、异步 |
|
||||
| [[TypeScript 基础]] | 进阶 | 类型系统、接口、泛型 |
|
||||
|
||||
## 学习建议
|
||||
|
||||
- **不要跳过基础直接学框架。** React 的 Hooks 本质就是 JS 闭包 + 状态管理,不懂 JS 就看不懂 Hooks。
|
||||
- **CSS 是前端最难的部分之一。** Flexbox 和 Grid 需要多动手练习,不是看几篇文章就能掌握的。
|
||||
- **TypeScript 不是可选的。** 现代前端项目中,TS 是标配,越早适应越好。
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[30.areas/finance/Investment lessons/2024.Current trading lessons.md]]
|
||||
@@ -0,0 +1,156 @@
|
||||
---
|
||||
tags: [前端, TypeScript, 基础]
|
||||
create time: 2026-04-24 18:41
|
||||
---
|
||||
|
||||
# TypeScript 基础
|
||||
|
||||
## 概述
|
||||
|
||||
TypeScript 是 JavaScript 的超集,在 JS 的基础上增加了类型系统。它的核心理念:**用类型在编译阶段捕获错误,而不是在运行时才发现 bug。**
|
||||
|
||||
思考题:JavaScript 是动态类型语言,TypeScript 是静态类型语言——它们到底有什么区别?为什么大型前端项目必须用 TypeScript?
|
||||
|
||||
## 正文
|
||||
|
||||
### 1. 类型注解
|
||||
|
||||
```typescript
|
||||
// 基本类型注解
|
||||
let userName: string = "Alice";
|
||||
let age: number = 25;
|
||||
let isActive: boolean = true;
|
||||
let scores: number[] = [90, 85, 92]; // 数组
|
||||
let tuple: [string, number] = ["Alice", 25]; // 元组
|
||||
|
||||
// 对象类型
|
||||
interface User {
|
||||
name: string;
|
||||
age: number;
|
||||
email?: string; // ? 表示可选属性
|
||||
}
|
||||
|
||||
const user: User = {
|
||||
name: "Alice",
|
||||
age: 25,
|
||||
email: "alice@example.com",
|
||||
};
|
||||
```
|
||||
|
||||
> **提问:** `string` 和 `String`(首字母小写 vs 大写)有什么区别?为什么 TS 用小写?
|
||||
|
||||
### 2. 联合类型与类型守卫
|
||||
|
||||
```typescript
|
||||
// 联合类型:一个变量可以是多种类型
|
||||
let value: string | number = "hello";
|
||||
value = 42; // ✅ 合法
|
||||
value = true; // ❌ 编译错误
|
||||
|
||||
// 类型守卫:在运行时判断具体类型
|
||||
function processValue(input: string | number) {
|
||||
if (typeof input === "string") {
|
||||
return input.toUpperCase(); // TS 知道这里是 string
|
||||
}
|
||||
return input.toFixed(2); // TS 知道这里是 number
|
||||
}
|
||||
|
||||
// 自定义类型守卫
|
||||
function isUser(obj: unknown): obj is User {
|
||||
return typeof obj === "object" && obj !== null && "name" in obj;
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 接口(Interface)vs 类型别名(Type Alias)
|
||||
|
||||
```typescript
|
||||
// Interface:适合定义对象形状,可扩展
|
||||
interface Animal {
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface Dog extends Animal {
|
||||
breed: string;
|
||||
}
|
||||
|
||||
// Type Alias:更灵活,可用于联合类型、元组等
|
||||
type ID = string | number;
|
||||
type Point = [number, number];
|
||||
type EventHandler = (event: MouseEvent) => void;
|
||||
```
|
||||
|
||||
> **核心区别:** Interface 可以被合并(declaration merging),Type Alias 不能。定义对象形状优先用 Interface,复杂类型用 Type。
|
||||
|
||||
### 4. 泛型(Generics)
|
||||
|
||||
```typescript
|
||||
// 泛型函数:类型参数化
|
||||
function identity<T>(arg: T): T {
|
||||
return arg;
|
||||
}
|
||||
|
||||
identity<string>("hello"); // 返回 string
|
||||
identity<number>(42); // 返回 number
|
||||
|
||||
// 泛型接口:React Props 的典型模式
|
||||
interface ApiResponse<T> {
|
||||
data: T;
|
||||
status: number;
|
||||
message: string;
|
||||
}
|
||||
|
||||
// 实际使用
|
||||
const response: ApiResponse<User[]> = {
|
||||
data: [{ name: "Alice", age: 25 }],
|
||||
status: 200,
|
||||
message: "success",
|
||||
};
|
||||
```
|
||||
|
||||
> **思考:** 为什么 React 组件的 Props 要用泛型?泛型如何让组件在复用时代码类型安全?
|
||||
|
||||
### 5. TS + React 实战示例
|
||||
|
||||
```typescript
|
||||
// 定义 Props 接口
|
||||
interface CounterProps {
|
||||
initialCount?: number;
|
||||
step?: number;
|
||||
onCountChange?: (count: number) => void;
|
||||
}
|
||||
|
||||
// 带泛型的 API 响应组件
|
||||
interface DataResponse<T> {
|
||||
data: T | null;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
}
|
||||
|
||||
// 组件实现
|
||||
const Counter: React.FC<CounterProps> = ({
|
||||
initialCount = 0,
|
||||
step = 1,
|
||||
onCountChange,
|
||||
}) => {
|
||||
const [count, setCount] = useState(initialCount);
|
||||
|
||||
const increment = () => {
|
||||
const newCount = count + step;
|
||||
setCount(newCount);
|
||||
onCountChange?.(newCount);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<span>Count: {count}</span>
|
||||
<button onClick={increment}>+{step}</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[JavaScript 基础]] — TypeScript 基于 JavaScript,TS 类型系统是对 JS 的增强
|
||||
- [[CSS 基础]] — TS 项目中常用的样式方案
|
||||
- [[30.areas/finance/Investment lessons/2024.Current trading lessons.md]]
|
||||
Reference in New Issue
Block a user