diff --git "a/\351\231\210\346\231\272\350\264\244/20250105-\345\210\235\345\205\245MVC.md" "b/\351\231\210\346\231\272\350\264\244/20250105-\345\210\235\345\205\245MVC.md" new file mode 100644 index 0000000000000000000000000000000000000000..9c1ef5abe44fd6c22d453b63e06e4fcbf373ff9e --- /dev/null +++ "b/\351\231\210\346\231\272\350\264\244/20250105-\345\210\235\345\205\245MVC.md" @@ -0,0 +1,28 @@ +# 初入MVC + +## 笔记 + +MVC(Model-View-Controller)是一种软件架构模式,将应用分为三个核心组件: + +**Model(模型)**:负责数据和业务逻辑,直接管理数据、规则和操作。不涉及任何界面展示。 + +**View(视图)**:用户界面层,展示数据并接收用户输入。通常是被动的,不处理业务逻辑。 + +**Controller(控制器)**:协调层,接收用户输入,调用模型处理数据,更新视图显示结果。充当Model和View之间的桥梁。 + +**工作流程**: + +1. 用户通过View交互 +2. Controller接收请求 +3. Controller调用Model处理业务 +4. Model更新数据并返回结果 +5. Controller将结果传递给View +6. View更新界面展示 + +**优点**:分离关注点、代码复用性高、便于团队协作。 + +**初学要点**:明确各层职责边界,避免将业务逻辑写入视图,保持控制器精简,让模型处理核心逻辑。这种分层思想是现代Web框架(如Spring MVC、ASP.NET MVC)的基础。 + +## 练习 + +无 diff --git "a/\351\231\210\346\231\272\350\264\244/20250107-\346\216\247\345\210\266\345\231\250.md" "b/\351\231\210\346\231\272\350\264\244/20250107-\346\216\247\345\210\266\345\231\250.md" new file mode 100644 index 0000000000000000000000000000000000000000..f950759279589d2e99255a287a875d2179856dd4 --- /dev/null +++ "b/\351\231\210\346\231\272\350\264\244/20250107-\346\216\247\345\210\266\345\231\250.md" @@ -0,0 +1,42 @@ +# 控制器 + +## 笔记 + +**控制器是MVC的协调中心**,接收用户请求,协调模型和视图完成响应。 + +**核心职责:** + +1. **请求处理**:接收并验证用户输入 +2. **业务协调**:调用模型执行业务逻辑 +3. **数据传递**:将处理结果传递给视图 +4. **流程控制**:决定下一步显示哪个视图 + +**设计原则:** + +- 保持“瘦控制器”,业务逻辑应放在模型中 +- 单一职责,每个控制器方法专注一个功能 +- 避免直接在控制器中操作数据库 +- 将数据验证委托给模型或专门的验证器 + +**典型工作流:** +用户请求 → 路由解析 → 控制器方法 → 调用模型 → 返回结果 → 渲染视图 + +**示例(伪代码):** + +```java +public class UserController { + public ActionResult Login(LoginRequest request) { + var user = userModel.Validate(request); // 调用模型 + if(user != null) { + return View("Dashboard", user); // 传递数据到视图 + } + return View("LoginError"); + } +} +``` + +控制器是MVC的“交通警察”,应专注流程控制而非业务实现。 + +## 练习 + +无 diff --git "a/\351\231\210\346\231\272\350\264\244/20250108-\350\247\206\345\233\276.md" "b/\351\231\210\346\231\272\350\264\244/20250108-\350\247\206\345\233\276.md" new file mode 100644 index 0000000000000000000000000000000000000000..56d0a4100e1607b878512ee13543d85959c5cf63 --- /dev/null +++ "b/\351\231\210\346\231\272\350\264\244/20250108-\350\247\206\345\233\276.md" @@ -0,0 +1,41 @@ +# 视图 + +## 笔记 + +**视图是MVC的展示层**,负责将数据呈现为用户界面,不包含业务逻辑。 + +**核心职责:** + +1. **数据展示**:将模型数据渲染为HTML/UI +2. **用户交互**:提供表单、按钮等交互元素 +3. **界面结构**:定义页面布局和视觉呈现 +4. **数据绑定**:动态显示模型状态变化 + +**设计原则:** + +- 保持“笨视图”,仅负责展示 +- 避免在视图中编写业务逻辑 +- 最小化视图中的代码逻辑 +- 使用模板语言分离结构和逻辑 + +**视图类型:** + +- **强类型视图**:绑定特定模型类型 +- **布局视图**:定义页面通用结构 +- **部分视图**:可重用的UI组件 +- **视图组件**:包含逻辑的独立UI单元 + +**示例(Razor视图):** + +```html +@model User +
上次登录:@Model.LastLogin
+ +``` + +视图应专注于“如何展示”,通过模板引擎实现数据与表现的分离,确保界面层的纯净和可维护性。 + +## 练习 + +无 diff --git "a/\351\231\210\346\231\272\350\264\244/20250109-\346\250\241\345\236\213.md" "b/\351\231\210\346\231\272\350\264\244/20250109-\346\250\241\345\236\213.md" new file mode 100644 index 0000000000000000000000000000000000000000..b6f04c97986daacf1090fa446dc1447339e2b288 --- /dev/null +++ "b/\351\231\210\346\231\272\350\264\244/20250109-\346\250\241\345\236\213.md" @@ -0,0 +1,48 @@ +# 模型 + +## 笔记 + +**模型是MVC的业务核心**,封装应用数据和业务规则,独立于用户界面。 + +**核心职责:** + +1. **数据管理**:定义数据结构、持久化操作 +2. **业务逻辑**:实现核心计算规则和业务流程 +3. **数据验证**:确保数据完整性和有效性 +4. **状态管理**:维护应用状态变更 + +**设计原则:** + +- 保持“胖模型”,集中存放业务逻辑 +- 独立于控制器和视图,可单独测试 +- 遵循单一职责,避免“上帝对象” +- 提供清晰的API供控制器调用 + +**模型类型:** + +- **领域模型**:封装业务实体和规则 +- **视图模型**:为特定视图优化的数据结构 +- **数据模型**:直接映射数据存储结构 + +**示例(伪代码):** + +```java +public class UserModel { + public User ValidateLogin(string username, string password) { + // 业务逻辑:验证用户 + var user = db.FindUser(username); + return VerifyPassword(user, password) ? user : null; + } + + public bool UpdateProfile(User user) { + // 业务逻辑:更新验证 + return Validate(user) && db.Update(user); + } +} +``` + +模型应专注于“做什么”,而非“如何展示”,确保业务逻辑的纯粹性和可重用性。 + +## 练习 + +无 diff --git "a/\351\231\210\346\231\272\350\264\244/20251230-\347\273\203\344\271\2409.md" "b/\351\231\210\346\231\272\350\264\244/20251230-\347\273\203\344\271\2409.md" new file mode 100644 index 0000000000000000000000000000000000000000..ee283668d3c6f3ded2c441368b6d90649305ff1f --- /dev/null +++ "b/\351\231\210\346\231\272\350\264\244/20251230-\347\273\203\344\271\2409.md" @@ -0,0 +1,93 @@ +# 练习9 + +## 笔记 + +## 核心数据结构与函数 + +### 6 + +```html + + +``` + +## 数组高阶函数 + +### 7 + +```html + + +``` + +### 8 + +```html + + +``` + +### 9 + +```html + + +``` + +### 10 + +```html + + +``` + +### 11 + +```html + + +``` diff --git "a/\351\231\210\346\231\272\350\264\244/20251231-\347\273\203\344\271\24010.md" "b/\351\231\210\346\231\272\350\264\244/20251231-\347\273\203\344\271\24010.md" new file mode 100644 index 0000000000000000000000000000000000000000..be10ddb2520b39f562a2a03ac292ced34b81e660 --- /dev/null +++ "b/\351\231\210\346\231\272\350\264\244/20251231-\347\273\203\344\271\24010.md" @@ -0,0 +1,71 @@ +# 练习10 + +## 笔记 + +## 数组高阶函数 + +### 12 + +```html +// 定义输入数组 +const arr = [1, 5, 3, -2, 8, -5]; + +// 使用 findIndex 查找第一个负数的索引 +const firstNegativeIndex = arr.findIndex(element => element < 0); + +// 输出结果 +console.log(firstNegativeIndex); // 输出:3 +``` + +### 13 + +```html +// 定义输入数组 +const arr = [1, 3, 5, 7, 8]; + +// 使用 some() 判断是否存在偶数 +const hasEvenNumber = arr.some(element => element % 2 === 0); + +// 输出结果 +console.log(hasEvenNumber); // 输出:true +``` + +### 14 + +```html +// 定义输入数组 +const arr = [1, 2, 3, 4, 5]; + +// 使用 every() 判断所有数字是否都大于 0 +const allGreaterThanZero = arr.every(element => element > 0); + +// 输出结果 +console.log(allGreaterThanZero); // 输出:true +``` + +### 15 + +```html +const arr = [40, 100, 1, 5, 25, 10]; +const sortedArr = [...arr].sort((a, b) => a - b); // 用扩展运算符复制数组 +console.log(arr); // 原数组不变:[40, 100, 1, 5, 25, 10] +console.log(sortedArr); // 排序后:[1, 5, 10, 25, 40, 100] +``` + +### 16 + +```html +// 定义学生对象数组 +const students = [ + {name: "小明", age: 20}, + {name: "小红", age: 18}, + {name: "小刚", age: 22} +]; + +// 按年龄从小到大排序(升序) +const sortedStudents = students.sort((a, b) => a.age - b.age); + +// 输出结果 +console.log(sortedStudents); +// 输出:[{name: "小红", age: 18}, {name: "小明", age: 20}, {name: "小刚", age: 22}] +``` diff --git "a/\351\231\210\346\231\272\350\264\244/20260104-\347\273\203\344\271\24011.md" "b/\351\231\210\346\231\272\350\264\244/20260104-\347\273\203\344\271\24011.md" new file mode 100644 index 0000000000000000000000000000000000000000..4f20f5eaff0f773a215e57b0834809fb1d8f4b95 --- /dev/null +++ "b/\351\231\210\346\231\272\350\264\244/20260104-\347\273\203\344\271\24011.md" @@ -0,0 +1,89 @@ +# 练习11 + +## 笔记 + +## 数组高阶函数 + +### 17 + +```html +// 定义输入数组 +const fruits = ['apple', 'banana', 'orange']; + +// 使用 forEach 遍历,输出索引和元素 +fruits.forEach((element, index) => { + // 按指定格式输出,多个结果拼接为一行(与示例输出格式一致) + process.stdout.write(`索引${index}: ${element} `); +}); +// 换行(优化输出格式) +console.log(); +``` + +### 18 + +```html +// 定义输入的二维数组 +const arr = [[1, 2], [3, 4], [5, 6]]; + +// 使用 reduce 扁平化数组 +const flattenedArr = arr.reduce((acc, current) => { + // acc 是累加器(初始为空数组),current 是当前遍历的子数组 + return acc.concat(current); // 合并累加器和当前子数组 +}, []); // 初始值设为空数组 + +// 输出结果 +console.log(flattenedArr); // 输出:[1, 2, 3, 4, 5, 6] +``` + +### 19 + +```html +// 定义输入数组 +const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple']; + +// 使用 reduce 统计元素出现次数 +const countObj = fruits.reduce((acc, current) => { + // 判断当前元素是否在累加器中,存在则+1,否则初始化为1 + acc[current] = (acc[current] || 0) + 1; + return acc; // 必须返回累加器,供下一次遍历使用 +}, {}); // 初始值设为空对象 + +// 输出结果 +console.log(countObj); // 输出:{ apple: 3, banana: 2, orange: 1 } +``` + +### 20 + +```html +// 定义输入的商品数组 +const products = [ + {name: "鼠标", price: 29}, + {name: "键盘", price: 89}, + {name: "显示器", price: 899}, + {name: "耳机", price: 199} +]; + +// 链式调用:筛选 → 排序 → 提取名称 +const result = products + .filter(item => item.price > 50) // 筛选价格>50的商品 + .sort((a, b) => a.price - b.price) // 按价格升序排序 + .map(item => item.name); // 只保留商品名称 + +// 输出结果 +console.log(result); // 输出:["键盘", "耳机", "显示器"] +``` + +### 21 + +```html +// 定义输入数组 +const nums = [2, 5, 8, 3, 9]; + +// 组合调用:先乘2(map),再筛选>10的数(filter) +const result = nums + .map(num => num * 2) // 第一步:[4, 10, 16, 6, 18] + .filter(num => num > 10); // 第二步:筛选出>10的数 → [16, 18] + +// 输出结果 +console.log(result); // 输出:[16, 18] +```