feat: v1.0.0 祀梦笔记:从 0 到 1 的数字化花园建设
This commit is contained in:
49
docs/notes/programming/c++/README.md
Normal file
49
docs/notes/programming/c++/README.md
Normal file
@@ -0,0 +1,49 @@
|
||||
---
|
||||
title: C++ 学习笔记
|
||||
description: 记录C++编程语言的学习心得和基础知识
|
||||
createTime: 2025/09/22 09:00:00
|
||||
permalink: /programming/cplusplus/
|
||||
---
|
||||
|
||||
# C++ 学习笔记
|
||||
|
||||
这里是我在学习C++编程语言过程中记录的学习心得、基础知识和实战经验。通过整理这些笔记,希望能够帮助自己和他人更好地掌握C++这门强大的编程语言。
|
||||
|
||||
## 学习路径
|
||||
|
||||
C++是一门复杂而强大的编程语言,学习路径建议如下:
|
||||
|
||||
1. **基础语法** - 掌握C++的基本语法和编程概念
|
||||
2. **面向对象编程** - 学习C++的类、继承、多态等OOP特性
|
||||
3. **STL标准库** - 熟悉常用的容器和算法
|
||||
4. **高级特性** - 模板、异常处理、智能指针等
|
||||
5. **实战项目** - 通过实际项目巩固所学知识
|
||||
|
||||
## 笔记分类
|
||||
|
||||
### 基础语法
|
||||
|
||||
- 数据类型
|
||||
- 运算符和表达式
|
||||
- 控制流语句
|
||||
- 函数
|
||||
|
||||
### 面向对象编程
|
||||
|
||||
- 类和对象
|
||||
- 继承与多态
|
||||
- 封装与抽象
|
||||
- 构造函数与析构函数
|
||||
|
||||
### STL标准库
|
||||
|
||||
- 容器(vector, list, map等)
|
||||
- 迭代器
|
||||
- 算法
|
||||
- 函数对象
|
||||
|
||||
## 学习资源推荐
|
||||
|
||||
- [C++ Primer Plus:中文版(第六版)](https://101su.ru/book/5442395/430bc1/c-primer-plus%E4%B8%AD%E6%96%87%E7%89%88%E7%AC%AC%E5%85%AD%E7%89%88.html) - 很好的C++入门教材
|
||||
|
||||
开始你的C++学习之旅吧!坚持学习,你会发现C++的魅力所在!
|
||||
10
docs/notes/programming/c++/basis.md
Normal file
10
docs/notes/programming/c++/basis.md
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title: C++ 简介与环境配置
|
||||
createTime: 2025/09/22 09:06:00
|
||||
permalink: /programming/cplusplus/basis/
|
||||
---
|
||||
|
||||
## C++的简介
|
||||
欢迎来到C++的奇妙世界~(๑>◡<๑) 如果你之前接触过C语言的话,那真是太棒啦!C++就像是C语言穿上了漂亮的新衣裳,不仅保留了原来的优点,还添加了面向对象和泛型编程的魔法哦~不过呢,可能需要稍微调整一下之前的编程习惯呢。就算你是第一次接触C++也完全不用担心,我会用最简单可爱的方式,带着你一步一步探索这个神奇的编程世界哒!
|
||||
|
||||
## 环境配置
|
||||
40
docs/notes/programming/leetcode/README.md
Normal file
40
docs/notes/programming/leetcode/README.md
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
title: LeetCode 题解笔记
|
||||
description: 记录LeetCode算法题的解题思路和代码实现
|
||||
createTime: 2025/09/22 08:09:52
|
||||
permalink: /programming/leetcode/
|
||||
---
|
||||
|
||||
# LeetCode 题解笔记
|
||||
|
||||
这里是我在LeetCode刷题过程中记录的解题思路和代码实现。通过整理这些题解,希望能够提高自己的算法水平和编程能力。
|
||||
|
||||
## 题解分类
|
||||
|
||||
### 数组与字符串
|
||||
|
||||
- [两数之和](https://leetcode-cn.com/problems/two-sum/)
|
||||
- [三数之和](https://leetcode-cn.com/problems/3sum/)
|
||||
|
||||
### 链表
|
||||
|
||||
- [反转链表](https://leetcode-cn.com/problems/reverse-linked-list/)
|
||||
- [合并两个有序链表](https://leetcode-cn.com/problems/merge-two-sorted-lists/)
|
||||
|
||||
### 动态规划
|
||||
|
||||
- [爬楼梯](https://leetcode-cn.com/problems/climbing-stairs/)
|
||||
- [最长回文子串](https://leetcode-cn.com/problems/longest-palindromic-substring/)
|
||||
|
||||
## 解题技巧
|
||||
|
||||
1. **双指针法**:常用于数组、链表问题,如两数之和、反转链表等
|
||||
2. **滑动窗口**:处理字符串子串问题
|
||||
3. **动态规划**:将原问题分解为子问题,自底向上求解
|
||||
4. **分治法**:将问题分成若干子问题,分别求解后合并结果
|
||||
|
||||
## 学习资源
|
||||
|
||||
- [LeetCode官方题解](https://leetcode-cn.com/problemset/all/)
|
||||
- [代码随想录](https://programmercarl.com/)
|
||||
- [算法导论](https://mitpress.mit.edu/books/introduction-algorithms)
|
||||
13
docs/notes/programming/leetcode/beginner.md
Normal file
13
docs/notes/programming/leetcode/beginner.md
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
title: LeetCode 入门题单~(≧∇≦)ノ
|
||||
description: 给算法初学者的题目推荐和学习路径
|
||||
createTime: 2025年9月22日 08:52:52
|
||||
permalink: /programming/leetcode/question_sheet/beginner/
|
||||
---
|
||||
# LeetCode 入门题单~(๑>◡<๑)
|
||||
|
||||
作为算法初学者,选择合适的题目开始练习真的超~级重要哦!这里给大家推荐一份超棒的入门题单——[「新」动计划 · 编程入门](https://leetcode.cn/studyplan/primers-list/) ~这份题单就像给小树苗精心准备的阳光和雨露一样,特别适合刚开始算法之旅的你~(悄悄告诉你,里面有两题是数据库基础,暂时可以跳过哦~)
|
||||
|
||||
我的小建议是:先自己试着挑战一下,如果遇到困难了,再来看题解也没关系~重要的是享受这个成长的过程呀~(♡˙︶˙♡)
|
||||
|
||||
## 基础语法 & 数据类型 ٩(๑>◡<๑)۶
|
||||
21
docs/notes/programming/solidity/README.md
Normal file
21
docs/notes/programming/solidity/README.md
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
title: Solidity 学习笔记
|
||||
description: 记录Solidity智能合约开发的学习心得和基础知识
|
||||
createTime: 2025/09/28 19:39:00
|
||||
permalink: /programming/solidity/
|
||||
---
|
||||
|
||||
## Solidity 智能合约概述
|
||||
|
||||
Solidity 是一种用于编写智能合约的静态类型编程语言,它运行在以太坊虚拟机(EVM)上。
|
||||
|
||||
## 推荐的资料
|
||||
推荐的编辑器
|
||||
|
||||
Remix IDE:[https://remix.ethereum.org/](https://remix.ethereum.org/)
|
||||
|
||||
有在线版本,也可以下载之后使用,而且可以通过 Docker 部署,很方便
|
||||
|
||||
Solidity 学习资料:
|
||||
- [Solidity 官方文档](https://docs.soliditylang.org/zh-cn/latest/index.html)
|
||||
- [cryptozombies](https://cryptozombies.io/zh/course)
|
||||
88
docs/notes/programming/solidity/basic-syntax.md
Normal file
88
docs/notes/programming/solidity/basic-syntax.md
Normal file
@@ -0,0 +1,88 @@
|
||||
---
|
||||
title: Solidity 基础语法与数据类型
|
||||
createTime: 2025/09/22 10:30:00
|
||||
permalink: /programming/solidity/basic-syntax/
|
||||
---
|
||||
|
||||
# Solidity 基础语法与数据类型~(≧∇≦)ノ
|
||||
|
||||
## Solidity 文件基础框架
|
||||
|
||||
Solidity 文件的基础框架通常包含以下几个部分:
|
||||
|
||||
1. **SPDX 许可证标识符 (SPDX License Identifier)**:为了避免法律问题和明确智能合约的开源许可证,建议在合约的开头添加 SPDX 许可证标识符。
|
||||
2. **Solidity 版本声明 (Pragma)**:这会告诉编译器您希望使用哪个版本的 Solidity 来编译您的代码。
|
||||
3. **ABI编码编译指示**:通过`pragma abicoder v1`或`pragma abicoder v2`来指定ABI编码版本。
|
||||
4. **合约定义 (Contract Definition)**:这是您编写智能合约代码的主体部分。
|
||||
|
||||
下面是一个基础的 Solidity 文件框架示例,您可以直接使用:
|
||||
|
||||
```solidity
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract MyContract {
|
||||
// 在这里编写您的合约代码
|
||||
}
|
||||
```
|
||||
|
||||
## Solidity 基础数据类型
|
||||
|
||||
- 布尔类型(bool):值为 `true` 和 `false`
|
||||
- 运算符:`!`(逻辑非)、`&&`(逻辑与)、`||`(逻辑或)、`==`(等于)、`!=`(不等于)
|
||||
- 整形(int/uint):
|
||||
- 有符号整数(int):可以表示负数和零。
|
||||
- 无符号整数(uint):只能表示非负数。
|
||||
- 整数类型可以是8位、16位、32位、64位或256位。(只要是八的倍数都可以)
|
||||
- 例如:`int8`、`uint256`等。
|
||||
- 运算符:
|
||||
- 比较运算符:`<=`,`<`,`>=`,`>`
|
||||
- 位运算符:`&`(按位与)、`|`(按位或)、`^`(按位异或)、`~`(按位取反)
|
||||
- 移位运算符:`<<`(左移)、`>>`(右移)
|
||||
- 算数运算符:`+`(加法)、`-`(减法)、`*`(乘法)、`/`(除法)、`%`(取余)
|
||||
- 对于一个整数类型`X`,可以使用`type(X).min`和`type(X).max`来获取其最小值和最大值。
|
||||
|
||||
|
||||
|
||||
## Solidity 基础语法结构
|
||||
|
||||
## Solidity 基础操作
|
||||
|
||||
### 导入其他源文件
|
||||
|
||||
Solidity 支持导入其他源文件,使用`import`语句。例如:
|
||||
|
||||
```solidity
|
||||
import "filename.sol";
|
||||
```
|
||||
|
||||
这将导入`filename.sol`文件中的合约代码。
|
||||
|
||||
还可以创建一个新的全局符号
|
||||
|
||||
```solidity
|
||||
import * as NewName from "filename.sol"
|
||||
```
|
||||
|
||||
这将创建一个新的全局符号`NewName`,您可以在合约中使用它来引用`filename.sol`文件中的合约,例如`NewName.ContractName`。
|
||||
|
||||
还可以在导入的同时重命名符号:`import {symbol1 as alias, symbol2} from "filename";`
|
||||
|
||||
### 注释
|
||||
|
||||
Solidity 支持两种类型的注释:
|
||||
|
||||
1. **行注释**:使用`//`来注释单行代码。
|
||||
2. **块注释**:使用`/*`和`*/`来注释多行代码。
|
||||
|
||||
例如:
|
||||
|
||||
```solidity
|
||||
// 这是一个行注释
|
||||
|
||||
/*
|
||||
这是一个
|
||||
块注释
|
||||
*/
|
||||
```
|
||||
922
docs/notes/programming/solidity/case-analysis.md
Normal file
922
docs/notes/programming/solidity/case-analysis.md
Normal file
@@ -0,0 +1,922 @@
|
||||
---
|
||||
title: 十份代码实例
|
||||
createTime: 2025/10/10 11:07:11
|
||||
permalink: /programming/solidity/analysis/case-analysis/
|
||||
password: simeng
|
||||
---
|
||||
|
||||
## 题目一
|
||||
|
||||
原题:
|
||||
|
||||
1.食品信息(FoodInfoItem)的接口编码
|
||||
|
||||
(1)编写食品信息实体的接口,完成可溯源食品信息初始化,实现可追溯的原始生产商食品信息上链功能
|
||||
|
||||
(2)编写分销商食品上链信息接口,根据食品溯源智能合约地址获取分销商上链食品的信息
|
||||
|
||||
(3)编写超市进行食品上链信息的接口,根据食品溯源智能合约地址获取超市上链食品信息。
|
||||
|
||||
2.食品溯源(Trace)的接口编码
|
||||
|
||||
(1)编写食品溯源智能合约生产商Producer添加食品接口,必须生产商才能添加可溯源的食品,实现溯源功能
|
||||
|
||||
(2)编写食品溯源智能合约分销商Distributor添加食品接口,必须分销商才能添加可溯源的食品,实现溯源功能
|
||||
|
||||
(3)编写食品溯源智能合约超市Retailer添加食品接口,必须超市才能添加可溯源的食品,实现溯源功能
|
||||
|
||||
3.角色(Role)管理的接口编码
|
||||
|
||||
(1)编写食品溯源增加角色接口,必须是未增加的角色才能被添加,实现添加角色的功能
|
||||
|
||||
(2)编写食品溯源移除角色接口,必须是已增加的角色才能被移除,实现移除角色的功能
|
||||
|
||||
(3)编写食品溯源角色授权接口,必须是授权的角色地址,实现角色权限管理功能
|
||||
|
||||
::: code-tabs
|
||||
@tab Distributor.sol
|
||||
```solidity
|
||||
pragma solidity ^0.4.25;
|
||||
|
||||
import "./Roles.sol";
|
||||
|
||||
//中间商角色
|
||||
contract Distributor {
|
||||
using Roles for Roles.Role;
|
||||
|
||||
event DistributorAdded(address indexed account);
|
||||
event DistributorRemoved(address indexed account);
|
||||
|
||||
Roles.Role private _distributors;
|
||||
|
||||
constructor (address distributor ) public {
|
||||
_addDistributor(distributor);
|
||||
}
|
||||
|
||||
modifier onlyDistributor() {
|
||||
require(isDistributor(msg.sender), "DistributorRole: caller does not have the Distributor role");
|
||||
_;
|
||||
}
|
||||
|
||||
function isDistributor(address account) public view returns (bool) {
|
||||
return _distributors.has(account);
|
||||
}
|
||||
|
||||
function addDistributor(address account) public onlyDistributor {
|
||||
_addDistributor(account);
|
||||
}
|
||||
|
||||
function renounceDistributor() public {
|
||||
_removeDistributor(msg.sender);
|
||||
}
|
||||
|
||||
function _addDistributor(address account) internal {
|
||||
_distributors.add(account);
|
||||
emit DistributorAdded(account);
|
||||
}
|
||||
|
||||
function _removeDistributor(address account) internal {
|
||||
_distributors.remove(account);
|
||||
emit DistributorRemoved(account);
|
||||
}
|
||||
}
|
||||
```
|
||||
@tab FoodInfoItem.sol
|
||||
```solidity
|
||||
pragma solidity >=0.4.22 <0.5.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
//食品信息管理合约
|
||||
// 1. 保存食品基本信息:时间戳(流转过程中),用户名(流转过程中),用户地址信息(流转过程中),食品质量(流转过程中),食物名称,当前用户名称,质量,状态.
|
||||
// 2. 对食品基本信息进行初始化
|
||||
// 3. 实现两个方法:中间商添加食品信息;超市添加食品信息
|
||||
// 4. 实现显示食品信息的方法
|
||||
|
||||
contract FoodInfoItem{
|
||||
uint[] _timestamp;//①保存食品流转过程中各个阶段的时间戳
|
||||
string[] _traceName;//②保存食品流转过程各个阶段的用户名
|
||||
address[] _traceAddress;//③保存食品流转过程各个阶段的用户地址信息(和用户一一对应)
|
||||
uint8[] _traceQuality;//④保存食品流转过程中各个阶段的质量
|
||||
string _name;//⑤食品名称
|
||||
string _currentTraceName;//⑥当前用户名称
|
||||
uint8 _quality;//⑦质量(0=优质 1=合格 2=不合格)
|
||||
uint8 _status;//⑧状态(0:生产 1:分销 2:出售)
|
||||
address _owner;//⑨初始化owner
|
||||
|
||||
constructor (string name, string traceName, uint8 quality, address producer) public {
|
||||
_timestamp.push(now);
|
||||
_traceName.push(traceName);
|
||||
_traceAddress.push(producer);
|
||||
_traceQuality.push(quality);
|
||||
_name = name;
|
||||
_currentTraceName = traceName;
|
||||
_quality = quality;
|
||||
_status = 0;
|
||||
_owner = msg.sender;
|
||||
}
|
||||
|
||||
function addTraceInfoByDistributor(string traceName,address distributor, uint8 quality) public returns(bool) {
|
||||
require(_status == 0 , "status must be producing");
|
||||
require(_owner == msg.sender,"only trace contract can invoke")
|
||||
//②
|
||||
_timestamp.push(now);
|
||||
_traceName.push(traceName);
|
||||
_currentTraceName = traceName;
|
||||
_traceAddress.push(distributor);
|
||||
_quality = quality;
|
||||
//③
|
||||
//④
|
||||
_traceQuality.push(_quality);
|
||||
_status = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
function addTraceInfoByRetailer(string traceName,address retailer, uint8 quality) public returns(bool) {
|
||||
require(_status == 1 , "status must be distributing");
|
||||
require(_owner == msg.sender,"only trace contract can invoke")
|
||||
//②
|
||||
_timestamp.push(now);
|
||||
_traceName.push(traceName);
|
||||
_currentTraceName = traceName;
|
||||
_traceAddress.push(retailer);
|
||||
_quality = quality;
|
||||
//③
|
||||
//④
|
||||
_traceQuality.push(_quality);
|
||||
_status = 2;
|
||||
return true;
|
||||
}
|
||||
function getTraceInfo() public constant returns(uint[], string[], address[], uint8[]) {
|
||||
return(_timestamp, _traceName, _traceAddress, _traceQuality);
|
||||
}
|
||||
|
||||
function getFood() public constant returns(uint, string, string, string, address, uint8) {
|
||||
return(_timestamp[0], _traceName[0], _name, _currentTraceName, _traceAddress[0], _quality);
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
@tab Producer.sol
|
||||
```solidity
|
||||
pragma solidity ^0.4.25;
|
||||
|
||||
import "./Roles.sol";
|
||||
|
||||
//生产者角色
|
||||
contract Producer {
|
||||
using Roles for Roles.Role;
|
||||
|
||||
event ProducerAdded(address indexed account);
|
||||
event ProducerRemoved(address indexed account);
|
||||
|
||||
Roles.Role private _producers;
|
||||
|
||||
constructor (address producer) public {
|
||||
_addProducer(producer);
|
||||
}
|
||||
|
||||
modifier onlyProducer() {
|
||||
require(isProducer(msg.sender), "ProducerRole: caller does not have the Producer role");
|
||||
_;
|
||||
}
|
||||
|
||||
function isProducer(address account) public view returns (bool) {
|
||||
return _producers.has(account);
|
||||
}
|
||||
|
||||
function addProducer(address account) public onlyProducer {
|
||||
_addProducer(account);
|
||||
}
|
||||
|
||||
function renounceProducer() public {
|
||||
_removeProducer(msg.sender);
|
||||
}
|
||||
|
||||
function _addProducer(address account) internal {
|
||||
_producers.add(account);
|
||||
emit ProducerAdded(account);
|
||||
}
|
||||
|
||||
function _removeProducer(address account) internal {
|
||||
_producers.remove(account);
|
||||
emit ProducerRemoved(account);
|
||||
}
|
||||
}
|
||||
```
|
||||
@tab Retailer.sol
|
||||
```solidity
|
||||
pragma solidity ^0.4.25;
|
||||
|
||||
import "./Roles.sol";
|
||||
|
||||
//零售商角色(超市)
|
||||
contract Retailer {
|
||||
using Roles for Roles.Role;
|
||||
|
||||
event RetailerAdded(address indexed account);
|
||||
event RetailerRemoved(address indexed account);
|
||||
|
||||
Roles.Role private _retailers;
|
||||
|
||||
constructor (address retailer) public {
|
||||
_addRetailer(retailer);
|
||||
}
|
||||
|
||||
modifier onlyRetailer() {
|
||||
require(isRetailer(msg.sender), "RetailerRole: caller does not have the Retailer role");
|
||||
_;
|
||||
}
|
||||
|
||||
function isRetailer(address account) public view returns (bool) {
|
||||
return _retailers.has(account);
|
||||
}
|
||||
|
||||
function addRetailer(address account) public onlyRetailer {
|
||||
_addRetailer(account);
|
||||
}
|
||||
|
||||
function renounceRetailer() public {
|
||||
_removeRetailer(msg.sender);
|
||||
}
|
||||
|
||||
function _addRetailer(address account) internal {
|
||||
_retailers.add(account);
|
||||
emit RetailerAdded(account);
|
||||
}
|
||||
|
||||
function _removeRetailer(address account) internal {
|
||||
_retailers.remove(account);
|
||||
emit RetailerRemoved(account);
|
||||
}
|
||||
}
|
||||
```
|
||||
@tab Roles.sol
|
||||
```solidity
|
||||
pragma solidity ^0.4.25;
|
||||
//角色库(管理所有角色地址)
|
||||
// 1. 实现增加角色地址
|
||||
// 2. 移除角色地址
|
||||
// 3. 判断角色地址是否被授权
|
||||
library Roles {
|
||||
struct Role {
|
||||
mapping (address => bool) bearer;
|
||||
}
|
||||
function add(Role storage role, address account) internal {
|
||||
require(!has(role, account), "Roles: account already has role");
|
||||
role.bearer[account] = true;
|
||||
}
|
||||
function remove(Role storage role, address account) internal {
|
||||
require(has(role, account), "Roles: account does not have role");
|
||||
role.bearer[account] = false;
|
||||
}
|
||||
function has(Role storage role, address account) internal returns (bool) {
|
||||
require(account != address(0), "Roles: account is the zero address");
|
||||
return role.bearer[account];
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
@tab Trace.sol
|
||||
```solidity
|
||||
pragma solidity >=0.4.22 <0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
import "./FoodInfoItem.sol";
|
||||
import "./Distributor.sol";
|
||||
import "./Producer.sol";
|
||||
import "./Retailer.sol";
|
||||
|
||||
//食品溯源合约(负责具体食品溯源信息的生成)
|
||||
// 1.实现生产食品的方法(新建食品信息)
|
||||
// 2.实现食品分销过程中增加溯源信息的接口
|
||||
// 3.实现食品出售过程中增加溯源信息的接口
|
||||
// 4.实现获取食品溯源信息接口
|
||||
|
||||
contract Trace is Producer, Distributor, Retailer{
|
||||
|
||||
mapping (uint256 => address) foods;//食品溯源id到具体食品溯源合约的映射表
|
||||
uint[] foodList;
|
||||
|
||||
//构造函数
|
||||
constructor(address producer, address distributor, address retailer)
|
||||
public Producer(producer)
|
||||
Distributor(distributor)
|
||||
Retailer(retailer){
|
||||
|
||||
}
|
||||
//生成食品溯源信息接口
|
||||
//只有Producer能调用
|
||||
//name 食品名称
|
||||
//traceNumber 食品溯源id
|
||||
//traceName 当前用户名称
|
||||
//quality 当前食品质量
|
||||
function newFood(string name,uint256 traceNumber, string traceName, uint8 quality)
|
||||
public onlyProducer returns(uint)
|
||||
{
|
||||
require(foods[traceNumber] == address(0),"traceName already exist");//④
|
||||
FoodInfoItem food = new FoodInfoItem(name,traceName,quality,msg.sender);//⑤
|
||||
foods[traceNumber] = food;//⑥
|
||||
foodList.push(traceNumber);//⑦
|
||||
retur food;//⑧
|
||||
}
|
||||
|
||||
//食品分销过程中增加溯源信息的接口
|
||||
//只有Distributor能调用
|
||||
//traceNumber 食品溯源id
|
||||
//traceName 当前用户名称
|
||||
//quality 当前食品质量
|
||||
function addTraceInfoByDistributor(uint256 traceNumber,string traceName, uint8 quality)
|
||||
public onlyRetailer returns(bool) {
|
||||
require(foods[traceNumber] != address(0),"traceNumber does not exist");
|
||||
//③
|
||||
return FoodInfoItem(foods[traceNumber]).addTraceInfoByDistributor(traceName,msg.sender, quality);
|
||||
}
|
||||
|
||||
//食品出售过程中增加溯源信息的接口
|
||||
//只有Retailer能调用
|
||||
//traceNumber 食品溯源id
|
||||
//traceName 当前用户名称
|
||||
//quality 当前食品质量
|
||||
function addTraceInfoByRetailer(uint256 traceNumber,string traceName, uint8 quality)
|
||||
public onlyRetailer returns(bool) {
|
||||
require(foods[traceNumber != address(0)], "traceNumber does not exist");
|
||||
return FoodInfoItem(foods[traceNumber]).addTraceInfoByRetailer(traceName,msg.sender, quality);
|
||||
}
|
||||
|
||||
//获取食品溯源信息接口
|
||||
//string[] 保存食品流转过程中各个阶段的相关信息
|
||||
//address[] 保存食品流转过程各个阶段的用户地址信息(和用户一一对应)
|
||||
//uint8[] 保存食品流转过程中各个阶段的状态变化
|
||||
function getTraceInfo(uint256 traceNumber) public constant returns(uint[], string[], address[], uint8[]) {
|
||||
require(foods[traceNumber] != address(0), "traceNumber does not exist");
|
||||
return FoodInfoItem(foods[traceNumber]).getTraceInfo();
|
||||
}
|
||||
|
||||
function getFood(uint256 traceNumber) public constant returns(uint, string, string, string, address, uint8) {
|
||||
require(foods[traceNumber] != address(0), "traceNumber does not exist");
|
||||
return FoodInfoItem(foods[traceNumber]).getFood();
|
||||
}
|
||||
|
||||
function getAllFood() public constant returns (uint[]) {
|
||||
return foodList;
|
||||
}
|
||||
}
|
||||
```
|
||||
:::
|
||||
## 题目二
|
||||
|
||||
题目:
|
||||
|
||||
1.供应链金融实体信息编码(6分)
|
||||
|
||||
(1)编写供应链金融智能合约的实体接口,完成实体通用数据的初始化,实现企业和票据实体信息上链的功能;(2分)
|
||||
|
||||
(2)编写企业上链信息接口,实现供应链金融的企业信息上链;(2分)
|
||||
|
||||
(3)基于给定的智能合约代码以及注释,完成银行向企业交易的接口函数;(2分)
|
||||
|
||||
2.供应链金融公司与公司接口编码(6分)
|
||||
|
||||
(1)编写公司与公司之间进行交易的历史存证上链接口,实现公司与公司之间的交易功能;(2分)
|
||||
|
||||
(2)编写创建存证的接口,实现创建存证的功能;(2分)
|
||||
|
||||
(3)编写交易金额数量变化的接口,实现凭证交易双方资金的变化功能;(2分)
|
||||
|
||||
3.供应链金融公司与银行交易的接口编码(4分)
|
||||
|
||||
(1)编写公司与银行之间进行交易的历史存证上链接口,实现公司与银行之间的交易功能;(2分)
|
||||
|
||||
(2)编写创建存证的接口,实现创建存证的功能;(1分)
|
||||
|
||||
(3)编写交易金额数量变化的接口,实现凭证交易双方资金的变化功能;(1分)
|
||||
|
||||
::: code-tabs
|
||||
@tab xxx.sol
|
||||
```solidity
|
||||
```
|
||||
@tab xxx.sol
|
||||
```solidity
|
||||
```
|
||||
@tab xxx.sol
|
||||
```solidity
|
||||
```
|
||||
:::
|
||||
## 题目三
|
||||
|
||||
题目:
|
||||
|
||||
子任务2-2-1:太阳能板管理接口编码
|
||||
|
||||
1. 根据文档要求,编写太阳能板新增接口功能,必须将新增太阳能板数据存入指定表中,在存储完成后需触发后事件并返回存储与否的标识;
|
||||
|
||||
2. 根据文档要求,编写太阳能板修改接口,必须通过指定表修改完成数据更新,在完成更新后需触发事件并返回更新与否的标识。
|
||||
|
||||
子任务2-2-2:能源管理接口编码
|
||||
|
||||
1. 根据文档要求,编写能源新增接口功能,必须将新增能源数据存入指定表中,在存储完成后需触发后事件并返回存储与否的标识;
|
||||
|
||||
2. 根据文档要求,编写能源修改接口,必须通过指定表修改完成数据更新,在完成更新后需触发事件并返回更新与否的标识。
|
||||
|
||||
子任务2-2-3:合约部署和调用
|
||||
|
||||
1. 解决代码错误和警告,正确编译并部署合约,成功获取部署的合约地址和ABI;
|
||||
|
||||
2. 调用太阳能板查询合约接口,完整验证业务流程;
|
||||
|
||||
3. 调用能源查询合约接口,完整验证业务流程。
|
||||
|
||||
::: code-tabs
|
||||
@tab xxx.sol
|
||||
```solidity
|
||||
```
|
||||
@tab xxx.sol
|
||||
```solidity
|
||||
```
|
||||
@tab xxx.sol
|
||||
```solidity
|
||||
```
|
||||
:::
|
||||
## 题目四
|
||||
|
||||
原题:
|
||||
|
||||
1.编写原材料接口newMaterial,初始化原材料信息,返回合约地址,并实现原材料信息上链功能。
|
||||
|
||||
2.编写获取存原材料接口getMaterial,根据合约地址获取原材料信息
|
||||
|
||||
3.编写食品物流上链接口addLogistic,实现食品物流信息上链功能
|
||||
|
||||
4.编写获取食品物流信息的接口getLogistics,根据食品产品编号获取物流信息
|
||||
|
||||
::: code-tabs
|
||||
@tab Logistics.sol
|
||||
```solidity
|
||||
pragma solidity 0.6.10;
|
||||
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract Logistics {
|
||||
|
||||
struct LogisticsData {
|
||||
address cargo; //货物合约地址
|
||||
address orgin; //货物上级合约地址
|
||||
address destination; //货物下级合约地址
|
||||
string memo; //备注信息
|
||||
uint createdAt; //创建时间
|
||||
uint queryCount; //已查询次数
|
||||
}
|
||||
|
||||
LogisticsData[] private _logisticsData; //全部物流信息数组
|
||||
|
||||
uint public recordCount;//所有记录条数
|
||||
uint public queryCount;//所有查询次数
|
||||
|
||||
//可自行添加形参和返回值
|
||||
function addLogistics(address _cargo,address _orgin,【请补充】) public {
|
||||
//TODO:”请补充缺失代码
|
||||
}
|
||||
|
||||
//可自行添加形参和返回值
|
||||
function getLogisticsInfo(address _cargo) public returns(LogisticsData[] memory _cargoLogisticsData) {
|
||||
|
||||
//TODO:”请补充缺失代码
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
@tab Material.sol
|
||||
```solidity
|
||||
pragma solidity 0.6.10;
|
||||
|
||||
contract Material {
|
||||
struct Material {
|
||||
address owner;
|
||||
string name;
|
||||
string id;
|
||||
string memo;
|
||||
uint createdAt;
|
||||
bool exist;
|
||||
}
|
||||
|
||||
mapping(string => Material) public materials;
|
||||
//可自行添加形参和返回值
|
||||
function newMaterial(string memory _name,string memory _id,【请补充】) public {
|
||||
|
||||
//TODO:”请补充缺失代码
|
||||
}
|
||||
|
||||
|
||||
//可自行添加形参和返回值
|
||||
function getMaterial(string memory id) public view returns(【请补充】) {
|
||||
|
||||
//TODO:”请补充缺失代码
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
参考答案:
|
||||
|
||||
::: code-tabs
|
||||
@tab Logistics.sol
|
||||
```solidity
|
||||
pragma solidity 0.6.10;
|
||||
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract Logistics {
|
||||
|
||||
struct LogisticsData {
|
||||
address cargo; //货物合约地址
|
||||
address orgin; //货物上级合约地址
|
||||
address destination; //货物下级合约地址
|
||||
string memo; //备注信息
|
||||
uint createdAt; //创建时间
|
||||
uint queryCount; //已查询次数
|
||||
}
|
||||
|
||||
LogisticsData[] private _logisticsData; //全部物流信息数组
|
||||
|
||||
uint public recordCount;//所有记录条数
|
||||
uint public queryCount;//所有查询次数
|
||||
|
||||
//可自行添加形参和返回值
|
||||
function addLogistics(address _cargo,address _orgin,【请补充】) public {
|
||||
//TODO:”请补充缺失代码
|
||||
}
|
||||
|
||||
//可自行添加形参和返回值
|
||||
function getLogisticsInfo(address _cargo) public returns(LogisticsData[] memory _cargoLogisticsData) {
|
||||
|
||||
//TODO:”请补充缺失代码
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
@tab Material.sol
|
||||
```solidity
|
||||
pragma solidity 0.6.10;
|
||||
|
||||
contract Material {
|
||||
struct Material {
|
||||
address owner;
|
||||
string name;
|
||||
string id;
|
||||
string memo;
|
||||
uint createdAt;
|
||||
bool exist;
|
||||
}
|
||||
|
||||
mapping(string => Material) public materials;
|
||||
//可自行添加形参和返回值
|
||||
function newMaterial(string memory _name,string memory _id,【请补充】) public {
|
||||
|
||||
//TODO:”请补充缺失代码
|
||||
}
|
||||
|
||||
|
||||
//可自行添加形参和返回值
|
||||
function getMaterial(string memory id) public view returns(【请补充】) {
|
||||
|
||||
//TODO:”请补充缺失代码
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
## 题目五
|
||||
|
||||
题目:
|
||||
|
||||
1.个人签章信息接口编码
|
||||
|
||||
(1)编写个人签章智能合约的实体接口,完成实体通用数据的初始化,实现签章和用户实体信息上链的功能
|
||||
|
||||
(2)编写签章信息上链的接口,实现Seal合约的构造函数;
|
||||
|
||||
(3)基于给定的智能合约代码以及注释,完成ElectronicSeal合约判断多人签章文件编号是否存在的函数。
|
||||
|
||||
2.电子印章接口编码
|
||||
|
||||
(1)基于给定的智能合约代码以及注释,完成ElectronicSeal合约获取多人签章信息函数;
|
||||
|
||||
(2)基于给定的智能合约代码以及注释,完成ElectronicSeal合约多人签章函数。
|
||||
|
||||
::: code-tabs
|
||||
@tab xxx.sol
|
||||
```solidity
|
||||
```
|
||||
:::
|
||||
## 题目六
|
||||
|
||||
题目:
|
||||
|
||||
1.食品信息(Food)、成员信息(Member)、生产订单信息(Productions)的结构体功能编码(6分)
|
||||
|
||||
(1)编写食品信息实体功能。(2分)
|
||||
|
||||
(2)完善智能合约中用户结构体内容(2分)
|
||||
|
||||
(3)编写生产订单(Productions)结构体信息。(2分)
|
||||
|
||||
2.食品溯源(Trace)的接口编码(6分)
|
||||
|
||||
(1)根据食品信息结构体,完成食品信息添加相应功能(2分)
|
||||
|
||||
(2)编写食品溯源收购商创建收购订单功能。
|
||||
|
||||
(3)编写食品溯源创建运输订单功能。
|
||||
|
||||
3.角色(Role)管理的接口编码(4分)
|
||||
|
||||
(1)编写食品溯源增加角色接口,实现添加角色的功能。(1分)
|
||||
|
||||
(2)编写食品溯源获取角色功能。(1分)
|
||||
|
||||
(3)编写食品溯源修改角色功能。(2分)
|
||||
|
||||
::: code-tabs
|
||||
@tab xxx.sol
|
||||
```
|
||||
```
|
||||
:::
|
||||
## 题目七
|
||||
|
||||
原题:
|
||||
**子任务2-2-1:航班延误保险购买合约编码(5分)**
|
||||
|
||||
(1)编写航班保险购买上链接口,完成只有购买机票的用户可以购买保险、必须缴纳正确的保费金额、购买保险的时间不能超过购买机票后的0.5小时的功能,符合条件则用户可以购买保险,将用户购买保险状态上链;(3分)
|
||||
|
||||
(2)编写退保接口,完成保险公司预存赔偿金后,用户无法退保,反之用户可退保的功能,将用户退保状态上链,并退还用户保费功能。(2分)
|
||||
|
||||
**子任务2-2-2:航班信息存证上链合约编码**
|
||||
|
||||
(1)编写获取航班信息接口,实现依据航班号获得航班号对应的计划起飞时间、实际起飞时间、到达时间、是否延误状态的功能;
|
||||
|
||||
(2)编写判断航班是否延误接口,实现依据航班号获得航班号对应的航班是否延误,得到航班是否延误的结果功能。
|
||||
|
||||
**子任务2-2-3:航班延误险理赔合约编码**
|
||||
|
||||
(1)编写客户理赔接口,实现如果航班延误超过4小时,将赔偿金赔偿给乘客的功能;
|
||||
|
||||
(2)编写保险公司收取保费接口,实现如果航班没有延误或者延误时间少于4小时,将保费转账给保险公司,并退还赔偿金的功能。
|
||||
|
||||
::: code-tabs
|
||||
@tab Claims.sol
|
||||
```solidity
|
||||
pragma solidity ^0.6.10;
|
||||
|
||||
import "./FlightDelayInsurance.sol";
|
||||
|
||||
contract Claims is FlightDelayInsurance{
|
||||
|
||||
// 定义航班信息结构体
|
||||
struct Flight {
|
||||
uint256 departureTime; // 航班出发时间
|
||||
uint256 delayTime; // 航班延误时间
|
||||
bool isDelayed; // 航班是否延误
|
||||
bool isInsured; // 航班是否购买保险
|
||||
}
|
||||
|
||||
// 定义保险公司地址
|
||||
address public insuranceCompany;
|
||||
|
||||
// 定义航班信息映射
|
||||
mapping(bytes32 => Flight) public flights;
|
||||
|
||||
// 定义购买保险事件
|
||||
event BuyInsurance(bytes32 flightKey, address passenger, uint256 premium);
|
||||
|
||||
// 定义航班延误事件
|
||||
event FlightDelay(bytes32 flightKey, uint256 delayTime);
|
||||
|
||||
// 定义理赔事件
|
||||
event Claim(bytes32 flightKey, address passenger, uint256 amount);
|
||||
|
||||
// 定义保险公司预存的赔偿金
|
||||
uint256 public compensationNew;
|
||||
|
||||
// 构造函数,初始化保险公司地址和赔偿金
|
||||
constructor() FlightDelayInsurance(platformS,airlineV,insuranceCompanyC,premium,compensation) public {
|
||||
insuranceCompany = msg.sender;
|
||||
compensationNew = compensation;
|
||||
}
|
||||
|
||||
// 更新航班信息函数
|
||||
function updateFlight(bytes32 flightKey, uint256 departureTime, uint256 delayTime, bool isDelayed) payable public {
|
||||
// 判断调用者是否为保险公司
|
||||
require(msg.sender == insuranceCompany, "Only insurance company can update flight information");
|
||||
// 更新航班信息
|
||||
flights[flightKey].departureTime = departureTime;
|
||||
flights[flightKey].isDelayed = isDelayed;
|
||||
|
||||
/*********** 客户理赔接口 **********/
|
||||
//任务2-2-3,请编写合约代码
|
||||
|
||||
|
||||
|
||||
/********** 客户理赔接口 ***********/
|
||||
|
||||
/*********** 保险公司收取保费接口开发 **********/
|
||||
//任务2-2-3,请编写合约代码
|
||||
|
||||
|
||||
|
||||
|
||||
/********** 保险公司收取保费接口开发 ***********/
|
||||
// 触发航班延误事件
|
||||
emit FlightDelay(flightKey, delayTime);
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
@tab FlightDelayInsurance.sol
|
||||
```solidity
|
||||
pragma solidity ^0.6.10;
|
||||
|
||||
contract FlightDelayInsurance {
|
||||
address public platformS; // 平台S的地址
|
||||
address public airlineV; // 航空公司V的地址
|
||||
address public insuranceCompanyC; // 保险公司C的地址
|
||||
uint public premium; // 保险费
|
||||
uint public compensation; // 赔偿金额
|
||||
uint public purchaseTime; // 购买保险的时间
|
||||
uint public depositTime; // 存入赔偿金额的时间
|
||||
bool public purchased; // 是否购买了保险
|
||||
bool public deposited; // 是否存入了赔偿金额
|
||||
mapping(address => bool) public insured; // 已退保的用户
|
||||
mapping(address => bool) public policy; // 已生成保单的用户
|
||||
mapping(address => bool) public purchasedTicket; // 已购买机票的用户
|
||||
|
||||
constructor(address _platformS, address _airlineV, address _insuranceCompanyC, uint _premium, uint _compensation) public {
|
||||
platformS = _platformS; // 初始化平台S的地址
|
||||
airlineV = _airlineV; // 初始化航空公司V的地址
|
||||
insuranceCompanyC = _insuranceCompanyC; // 初始化保险公司C的地址
|
||||
premium = _premium; // 初始化保险费
|
||||
compensation = _compensation; // 初始化赔偿金额
|
||||
}
|
||||
|
||||
function purchaseTicket() public {
|
||||
require(!purchasedTicket[msg.sender], "Ticket has already been purchased"); // 该用户已购买机票
|
||||
purchasedTicket[msg.sender] = true; // 标记该用户已购买机票
|
||||
purchaseTime = block.timestamp;
|
||||
}
|
||||
/*********** 航班保险购买上链接口开发 **********/
|
||||
//任务2-2-1,请编写合约代码
|
||||
|
||||
|
||||
|
||||
|
||||
/********** 航班保险购买上链接口开发 ***********/
|
||||
function depositCompensation() public payable {
|
||||
require(msg.sender == insuranceCompanyC, "Only insurance company C can deposit compensation"); // 只有保险公司C可以存入赔偿金额
|
||||
require(msg.value == compensation, "Compensation amount is incorrect"); // 赔偿金额不正确
|
||||
require(block.timestamp < depositTime + 2 hours, "Deposit time has expired"); // 存入赔偿金额的时间已过期
|
||||
deposited = true; // 标记已存入赔偿金额
|
||||
}
|
||||
|
||||
/*********** 退保接口开发 **********/
|
||||
//任务2-2-1,请编写合约代码
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/********** 退保接口开发 ***********/
|
||||
|
||||
function generatePolicy() public {
|
||||
require(deposited, "Compensation has not been deposited"); // 赔偿金额未存入,无法生成保单
|
||||
require(msg.sender == platformS, "Only platform S can generate policy"); // 只有平台S可以生成保单
|
||||
require(!policy[msg.sender], "Policy has already been generated"); // 该用户已生成保单
|
||||
policy[msg.sender] = true; // 标记该用户已生成保单
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
@tab FlightManagement.sol
|
||||
```solidity
|
||||
pragma solidity ^0.6.10;
|
||||
|
||||
contract FlightManagement {
|
||||
|
||||
// 航班结构体
|
||||
struct Flight {
|
||||
string flightNumber; // 航班号
|
||||
uint256 scheduledDepartureTime; // 计划起飞时间
|
||||
uint256 actualDepartureTime; // 实际起飞时间
|
||||
uint256 arrivalTime; // 到达时间
|
||||
bool delayed; // 是否延误
|
||||
}
|
||||
|
||||
// 航班号到航班信息的映射
|
||||
mapping(string => Flight) flights;
|
||||
|
||||
// 添加航班
|
||||
function addFlight(string memory _flightNumber, uint256 _scheduledDepartureTime, uint256 _arrivalTime) public {
|
||||
flights[_flightNumber] = Flight(_flightNumber, _scheduledDepartureTime, 0, _arrivalTime, false);
|
||||
}
|
||||
|
||||
// 更新实际起飞时间
|
||||
function updateActualDepartureTime(string memory _flightNumber, uint256 _actualDepartureTime) public {
|
||||
flights[_flightNumber].actualDepartureTime = _actualDepartureTime;
|
||||
}
|
||||
|
||||
/*********** 获取航班信息接口开发 **********/
|
||||
//任务2-2-2,请编写合约代码
|
||||
|
||||
|
||||
|
||||
|
||||
/********** 获取航班信息接口开发 ***********/
|
||||
|
||||
/*********** 编写判断航班是否延误接口开发 **********/
|
||||
//任务2-2-2,请编写合约代码
|
||||
|
||||
|
||||
|
||||
|
||||
/********** 编写判断航班是否延误接口开发 ***********/
|
||||
}
|
||||
|
||||
```
|
||||
:::
|
||||
## 题目八
|
||||
|
||||
题目:
|
||||
子任务2-2-1:信息管理合约编码
|
||||
1. 编写检索个人信息接口,完成患者通过身份证号检索其姓名、性别、年龄的功能;
|
||||
2. 编写信息管理接口,完成允许患者与医院和科室进行信息管理,通过身份证号检索到患者的个人信息,将预约信息显示给患者,并发送到患者的账户地址中的功能;
|
||||
子任务2-2-2:病历管理合约编码
|
||||
1. 编写新建病历接口,实现检索病人对应科室既往病历,授权医生查看,如果没有既往病历则创建一个新的病历功能;
|
||||
2. 编写结束就诊接口,实现检查病历是否已经填写,并结束病历咨询的功能。
|
||||
子任务2-2-3:病历查看合约编码
|
||||
根据需求用例文档在待补充源码中完成病历查看合约的编码,解决代码错误和警告,正确编译合约,功能调试正确,运行合约中的检查退款请求状态、自动批准退款请求接口功能。
|
||||
1.编写查看病人个人信息接口,实现获取指定病人个人信息功能;
|
||||
2.编写查看病人病情描述接口,实现获取指定病人病情描述功能。
|
||||
::: code-tabs
|
||||
@tab xxx.sol
|
||||
```
|
||||
```
|
||||
:::
|
||||
## 题目九
|
||||
|
||||
题目:
|
||||
|
||||
子任务2-2-1:合同管理合约编码
|
||||
|
||||
(1)编写房东签署合同接口,完成本合同位置只允许房东签署,通过合同中的信息生成租赁合同的链上哈希,触发协议签署合同的功能,其中合同中的信息包括房东链上账户、租客链上账户、租赁开始时间、租赁结束时间、月租金额、押金金额、交租时间;
|
||||
|
||||
(2)编写租金支付接口,完成只允许租客支付租金的规则,检查支付的租金金额是否正确,触发记录租金支付情况的功能。
|
||||
|
||||
子任务2-2-2:违约管理合约编码
|
||||
|
||||
(1)编写房东终止合同接口,实现房东终止合同判断,如果租客已经终止合同则合同无效,如果合同有效,对合同终止状态进行标记,将剩余押金退还给租客的功能;
|
||||
|
||||
(2)编写租客终止合同接口,实现租客终止合同判断,如果房东已经终止合同则合同无效,如果合同有效,对合同终止状态进行标记,将剩余押金退还给房东的功能。
|
||||
|
||||
子任务2-2-3:押金管理合约编码
|
||||
|
||||
根据需求用例文档在待补充源码中完成押金管理合约的编码,解决代码错误和警告,正确编译合约,功能调试正确,运行合约中的租客缴纳押金情况查询、房东收取押金情况查询接口功能。
|
||||
|
||||
(1)编写租客缴纳押金情况查询接口,实现查询租客是狗已缴纳押金功能;
|
||||
|
||||
(2)编写房东收取押金情况查询接口,实现房东是否已收到押金的功能。
|
||||
|
||||
::: code-tabs
|
||||
@tab xxx.sol
|
||||
```
|
||||
```
|
||||
:::
|
||||
## 题目十
|
||||
|
||||
题目:
|
||||
|
||||
子任务2-2-1:账户管理合约编码
|
||||
|
||||
根据需求用例文档在待补充源码中完成账户管理合约的编码,解决代码错误和警告,正确编译合约,功能调试正确。需要编写生成账户接口,完成从外部部门检索姓名、年龄、雇主、开始日期、工资、缴费基数,将人员信息进行综合存储功能。
|
||||
|
||||
子任务2-2-2:费用管理合约编码
|
||||
|
||||
根据需求用例文档在待补充源码中完成费用管理合约的编码,解决代码错误和警告,正确编译合约,功能调试正确,运行添加新职工账户、添加新雇主账户。
|
||||
|
||||
1.编写添加新职工账户接口,实现当账户不存在,只有管理员可以添加职工账户,职工新账户中账户余额为0,未被赞助的功能;
|
||||
|
||||
2.编写添加新雇主账户接口,实现当账户不存在,只有管理员可以添加雇主账户,雇主新账户中账户余额为0,已被赞助的功能;
|
||||
|
||||
子任务2-2-3:保险转移合约编码
|
||||
|
||||
根据需求用例文档在待补充源码中完成保险转移合约的编码,解决代码错误和警告,正确编译合约,功能调试正确,运行合约中的申请转移关系、接收账户转移接口。
|
||||
|
||||
1.编写申请转移关系接口,实现创建申请、添加到申请列表功能,其中创建申请需要设置申请人地址、原城市、目标城市、停缴状态、批准状态;
|
||||
|
||||
2.编写接收账户转移接口,实现获取账户,进行账户授权状态、接收状态、个人账户基金、统筹账户基金、养老保险账户的信息设置;
|
||||
|
||||
::: code-tabs
|
||||
@tab xxx.sol
|
||||
```
|
||||
```
|
||||
:::
|
||||
56
docs/notes/programming/solidity/other/hardhat.md
Normal file
56
docs/notes/programming/solidity/other/hardhat.md
Normal file
@@ -0,0 +1,56 @@
|
||||
---
|
||||
title: Hardhat 相关知识
|
||||
createTime: 2025/10/14 14:57:06
|
||||
permalink: /programming/solidity/other/hardhat/
|
||||
---
|
||||
|
||||
## HardHat2 部署
|
||||
### Node.js v16 安装
|
||||
HardHat2 需要 Node.js v16 及以上的版本
|
||||
这里给出的是通过 npm 来将旧版本升级到 Node.js v16 的,如果想要直接安装的话通过 `yum install nodejs` 或者 `apt install nodejs` 来即可。
|
||||
```bash
|
||||
npm config set registry https://registry.npmmirror.com
|
||||
sudo npm install -g n
|
||||
sudo n 16
|
||||
```
|
||||
安装完成之后可以查看版本,如果没有更新可以重新刷新一下环境(直接退出重连最简单)
|
||||
```bash
|
||||
node -v
|
||||
# v16.20.2
|
||||
npm -v
|
||||
# 6.14.15
|
||||
```
|
||||
### 安装 Hardhat2
|
||||
创建一个 hardhat2-project 目录,初始化 npm 项目,注意这里不要用 hardhat 作为项目名
|
||||
```bash
|
||||
mkdir ~/hardhat2-project
|
||||
cd ~/hardhat2-project
|
||||
npm init -y
|
||||
```
|
||||
安装 Hardhat 2
|
||||
```bash
|
||||
npm install --save-dev hardhat@^2.23.0
|
||||
```
|
||||
初始化 Hardhat2 项目
|
||||
```bash
|
||||
npx hardhat init
|
||||
```
|
||||
选择
|
||||
```bash
|
||||
✔ What do you want to do? · Create a JavaScript project
|
||||
✔ Hardhat project root: · /root/hardhat2-project
|
||||
✔ Do you want to add a .gitignore? (Y/n) · y
|
||||
✔ Help us improve Hardhat with anonymous crash reports & basic usage data? (Y/n) · y
|
||||
✔ Do you want to install this sample project's dependencies with npm (@nomicfoundation/hardhat-toolbox)? (Y/n) · y
|
||||
```
|
||||
## 使用 Hardhat2 编译测试合约
|
||||
在 hardhat2-project 目录下,执行以下命令来编译合约
|
||||
合约都会放在 `contracts` 目录下,这里我们选择了一个默认的合约,因此可以直接编译
|
||||
```bash
|
||||
# 测试编译
|
||||
npx hardhat compile
|
||||
# 运行测试
|
||||
npx hardhat test
|
||||
# 查看可用任务
|
||||
npx hardhat help
|
||||
```
|
||||
88
docs/notes/programming/solidity/other/miscellaneous.md
Normal file
88
docs/notes/programming/solidity/other/miscellaneous.md
Normal file
@@ -0,0 +1,88 @@
|
||||
---
|
||||
title: 一些没分类的小知识
|
||||
createTime: 2025/10/12 15:34:38
|
||||
permalink: /programming/solidity/other/miscellaneous/
|
||||
---
|
||||
|
||||
## 关于 memory 和 storage 存储类型
|
||||
|
||||
- `storage`:合约的持久化状态数据,保存在链上状态。对 `storage` 的写入最昂贵,读取也比内存贵;修改会永久生效。
|
||||
- `memory`:函数调用期间的临时数据,函数返回后即释放。对 `memory` 的更改不会持久化。
|
||||
- (补充)`calldata`:外部函数参数的只读数据位置,零拷贝、不可修改,用于节省 gas。
|
||||
|
||||
### 生命周期与成本
|
||||
- `storage` 写入昂贵、读取较贵;适合保存需要长期存在的状态。
|
||||
- `memory` 在函数结束时释放,读取/写入相对便宜;适合临时计算与返回值。
|
||||
- 复杂引用类型(数组、`struct`、`mapping`、`string`、`bytes`)在函数参数或局部变量处通常必须显式标注数据位置。
|
||||
|
||||
### 默认与必须声明
|
||||
- 状态变量总是位于 `storage`(例如 `User[] public users;`)。
|
||||
- 外部函数(`external`)的复杂类型参数默认是 `calldata`;内部/公共函数需要显式标注 `memory` 或 `storage`。
|
||||
- 局部变量的复杂类型必须指定数据位置,否则编译报错。
|
||||
|
||||
### 拷贝与引用语义
|
||||
- 从 `storage` 读取到 `memory` 会“复制”数据;修改 `memory` 副本不影响原始 `storage`。
|
||||
- 使用 `storage` 局部变量可以得到对状态数据的“引用”,对其赋值会持久化。
|
||||
|
||||
```solidity
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
contract Users {
|
||||
struct User { string name; uint age; }
|
||||
User[] public users;
|
||||
|
||||
function add(string memory name, uint age) external {
|
||||
users.push(User(name, age)); // 写入 storage
|
||||
}
|
||||
|
||||
function updateName(uint i, string memory newName) external {
|
||||
User storage u = users[i]; // storage 引用(指向链上状态)
|
||||
u.name = newName; // 修改持久化生效
|
||||
}
|
||||
|
||||
function tryUpdate(uint i) external {
|
||||
User memory u = users[i]; // 从 storage 复制到 memory
|
||||
u.age = 99; // 仅修改副本,不会影响链上状态
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 在内部函数传递 storage 引用
|
||||
- 仅内部/私有函数可以接收 `storage` 引用参数,从而直接修改状态;外部函数参数不能是 `storage`。
|
||||
|
||||
```solidity
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
contract Users2 {
|
||||
struct User { string name; uint age; }
|
||||
User[] public users;
|
||||
|
||||
function _inc(User storage u) internal { u.age += 1; }
|
||||
|
||||
function birthday(uint i) external {
|
||||
_inc(users[i]); // 传递 storage 引用,持久化修改
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 动态 memory 数组与限制
|
||||
- 可在 `memory` 中构造动态数组:`new uint[](n)`;适合作为返回值或临时计算。
|
||||
- `mapping` 只能存在于 `storage`,不能在 `memory` 中创建或拷贝。
|
||||
|
||||
```solidity
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
contract Arrays {
|
||||
function make(uint n) external pure returns (uint[] memory a) {
|
||||
a = new uint[](n);
|
||||
for (uint i = 0; i < n; i++) a[i] = i;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 常见坑与实践建议
|
||||
- 给 `storage` 变量整体赋值会进行深拷贝或引用变更(依据类型),要明确拷贝成本与语义。
|
||||
- 修改 `memory` 副本不会持久化;要修改链上状态请使用 `storage` 引用。
|
||||
- 大型 `string/bytes/数组` 在 `memory↔storage` 间复制成本高,尽量减少不必要的复制。
|
||||
- 外部函数能用 `calldata` 的地方尽量使用(只读参数),节省 gas。
|
||||
|
||||
90
docs/notes/programming/web/README.md
Normal file
90
docs/notes/programming/web/README.md
Normal file
@@ -0,0 +1,90 @@
|
||||
---
|
||||
title: Web 概览与学习路径
|
||||
permalink: /programming/web/
|
||||
createTime: 2025/10/28 22:20:00
|
||||
---
|
||||
|
||||
# Web 是什么?
|
||||
|
||||
Web(万维网)是一个基于浏览器与服务器的“信息与应用平台”。用户通过浏览器访问网站,浏览器通过 **HTTP/HTTPS** 与服务器交互,服务器返回页面或数据,最终在浏览器中呈现并产生交互。
|
||||
|
||||
- 浏览器:渲染页面(HTML/CSS/JS)、执行脚本、发起网络请求。
|
||||
- 服务器:处理业务逻辑、读写数据库、对外提供 API。
|
||||
- 数据库:持久化存储(MySQL/PostgreSQL/MongoDB 等)。
|
||||
|
||||
简而言之:浏览器负责“看与用”,服务器负责“算与存”。
|
||||
|
||||
## 前端基础概念
|
||||
|
||||
- HTML:结构与语义(页面“骨架”)。
|
||||
- CSS:表现与布局(页面“外观”)。
|
||||
- JavaScript:交互与逻辑(页面“大脑”)。
|
||||
- 现代前端:模块化、构建工具、组件化框架(Vue/React/Svelte 等)。
|
||||
|
||||
入门建议:先掌握原生 HTML/CSS/JS,再学习框架。你可以从本站文章开始:
|
||||
- 基础教程 → `/programming/web/basic-syntax/html-css-js/`
|
||||
|
||||
## 后端基础概念
|
||||
|
||||
- 服务器与框架:Node.js(Express/NestJS)、Python(Flask/Django/FastAPI)、Java(Spring Boot)、Go(Gin/Fiber)。
|
||||
- API 风格:REST(常见)、GraphQL(灵活查询)。
|
||||
- 数据库与 ORM:MySQL/PostgreSQL(关系型)、MongoDB(文档型);ORM 如 Prisma/TypeORM/SQLAlchemy。
|
||||
- 常见能力:认证授权(Session/JWT/OAuth)、文件上传、任务队列、缓存、日志与监控。
|
||||
|
||||
## 前后端如何协作
|
||||
|
||||
- 约定接口:路径、方法(GET/POST/PUT/DELETE)、参数与返回 JSON。
|
||||
- 跨域与安全:CORS、CSRF/XSS/SQL 注入防护、HTTPS。
|
||||
- 开发流程:
|
||||
1) 需求与原型 → 2) API 设计 → 3) 前端页面与交互 → 4) 后端实现与测试 → 5) 联调与验收 → 6) 部署与监控。
|
||||
|
||||
## 学习路径(从 0 到 1)
|
||||
|
||||
1. 基础三件套:HTML + CSS + JavaScript(建议用 VSCode + Live Server)。
|
||||
2. 工具与方法:Git/GitHub、浏览器开发者工具、HTTP/REST、请求调试(Postman/Insomnia)。
|
||||
3. 进阶前端:布局(Flex/Grid)、响应式、ES6+、模块化、打包与构建(Vite/Webpack)。
|
||||
4. 后端入门:选择一种语言与框架(如 Node.js + Express),完成 CRUD 与认证。
|
||||
5. 数据库:会建表、会写基本查询;理解事务与索引。
|
||||
6. 部署与上线:Nginx 反向代理、Docker、环境变量、日志与监控。
|
||||
|
||||
建议开发一个“待办清单 + 登录 + 数据持久化”的完整小项目,贯穿前后端与部署。
|
||||
|
||||
## 推荐学习资源
|
||||
|
||||
通用与入门:
|
||||
- [MDN Web Docs(HTML/CSS/JS 全面权威)](https://developer.mozilla.org/)
|
||||
- [freeCodeCamp(系统课程与练习)](https://www.freecodecamp.org/)
|
||||
- [Roadmap.sh(前端/后端学习路径图)](https://roadmap.sh/)
|
||||
|
||||
前端:
|
||||
- [HTML/CSS 基础(MDN)](https://developer.mozilla.org/en-US/docs/Learn)
|
||||
- [CSS-Tricks(样式与布局技巧)](https://css-tricks.com/)
|
||||
- [JavaScript 基础与进阶(MDN)](https://developer.mozilla.org/en-US/docs/Web/JavaScript)
|
||||
- [Vue 官方文档](https://vuejs.org/)
|
||||
|
||||
后端:
|
||||
- [Node.js 文档](https://nodejs.org/en/docs)
|
||||
- [Express](https://expressjs.com/)
|
||||
- [NestJS](https://docs.nestjs.com/)
|
||||
- [Spring Boot](https://spring.io/projects/spring-boot)
|
||||
- [Django](https://docs.djangoproject.com/)
|
||||
- [Flask](https://flask.palletsprojects.com/)
|
||||
- [FastAPI](https://fastapi.tiangolo.com/)
|
||||
|
||||
数据库与 ORM:
|
||||
- [MySQL](https://dev.mysql.com/doc/)
|
||||
- [PostgreSQL](https://www.postgresql.org/docs/)
|
||||
- [MongoDB](https://www.mongodb.com/docs/)
|
||||
- [Prisma(Node.js ORM)](https://www.prisma.io/docs)
|
||||
- [TypeORM](https://typeorm.io/)
|
||||
|
||||
工具:
|
||||
- [VSCode](https://code.visualstudio.com/)
|
||||
- [Postman](https://www.postman.com/)
|
||||
- [Insomnia](https://insomnia.rest/)
|
||||
- [Docker](https://docs.docker.com/)
|
||||
|
||||
## 本站相关内容
|
||||
|
||||
- Web 前端基础讲解 → `/programming/web/basic-syntax/html-css-js/`
|
||||
- 后续将补充:前端工程化、接口联调、部署与运维实战等专题。
|
||||
535
docs/notes/programming/web/basic-syntax/html-css-js.md
Normal file
535
docs/notes/programming/web/basic-syntax/html-css-js.md
Normal file
@@ -0,0 +1,535 @@
|
||||
---
|
||||
title: Web 前端基础讲解
|
||||
createTime: 2025/10/28 21:23:48
|
||||
permalink: /programming/web/basic-syntax/html-css-js/
|
||||
---
|
||||
|
||||
## 前端开发到底是什么?
|
||||
|
||||
前端开发,简单来说,就是**你能在网页上看到和互动的一切**。
|
||||
|
||||
想象一下你正在看一个网站:
|
||||
|
||||
* **文字、图片、按钮、菜单**:这些都是前端开发人员用代码“画”出来的。
|
||||
* **点击按钮会发生什么、输入框能打字、图片能放大缩小**:这些互动效果也是前端开发人员用代码实现的。
|
||||
|
||||
所以,前端开发就是负责把设计师画好的网站样子,用代码变成用户可以在浏览器里真实看到、摸到、用的东西。它主要涉及三种技术:
|
||||
|
||||
1. **HTML**:就像网页的“骨架”,决定了网页上有什么内容(标题、段落、图片等)。
|
||||
2. **CSS**:就像网页的“衣服”,决定了网页看起来怎么样(颜色、字体、布局等)。
|
||||
3. **JavaScript**:就像网页的“大脑”,决定了网页能做什么(动画、交互、数据处理等)。
|
||||
|
||||
总而言之,前端开发就是让网站变得好看、好用、能互动。
|
||||
|
||||
## 开发工具
|
||||
|
||||
进行前端开发,我们需要一个好用的“工具箱”。其中,**Visual Studio Code (VS Code)** 是一个非常受欢迎且功能强大的选择。
|
||||
|
||||
VsCode 官网:[https://code.visualstudio.com/](https://code.visualstudio.com/)
|
||||
|
||||
**为什么推荐 VS Code?**
|
||||
|
||||
* **免费且开源**:你可以免费使用它,并且它的代码是公开的,有很多人一起维护和改进。
|
||||
* **轻量级但功能强大**:它启动速度快,占用资源少,但通过安装各种“插件”,可以实现非常多的功能,比如代码高亮、智能提示、调试、版本控制等等。
|
||||
* **支持多种语言**:不仅对 HTML、CSS、JavaScript 有很好的支持,也支持其他很多编程语言。
|
||||
* **丰富的生态系统**:有大量的插件可以帮助你提高开发效率,比如 Live Server(实时预览网页)、Prettier(代码格式化)等。
|
||||
* **跨平台**:无论你使用 Windows、macOS 还是 Linux,都可以安装和使用 VS Code。
|
||||
|
||||
### VsCode 前端开发插件推荐
|
||||
- **Chinese (Simplified) Language Pack for Visual Studio Code**:中文语言包,方便中文用户使用。
|
||||
- **Live Server**:实时预览网页,修改代码后自动刷新。
|
||||
- **Prettier**:代码格式化,保持代码风格统一。
|
||||
- **HTML CSS Support**:HTML 和 CSS 代码智能提示。
|
||||
|
||||
参考文章:
|
||||
1. [VSCode安装配置使用教程(最新版超详细保姆级含插件)一文就够了](https://blog.csdn.net/2303_82176667/article/details/137193809)
|
||||
2. [快速上手web前端开发(超详细教程)](https://blog.csdn.net/2303_82176667/article/details/137193809)
|
||||
|
||||
## HTML5 基础知识讲解
|
||||
|
||||
HTML 是一种用来描述网页的语言,用于描述网页的结构和内容。
|
||||
|
||||
HTML 并不是一种编程语言,而是一种标记语言。它使用标签来描述网页上的不同元素,比如标题、段落、图片、链接等。
|
||||
|
||||
标签指的是由尖括号 `<` 和 `>` 包围的关键词,通常成对出现,用来表示元素的开始和结束。
|
||||
|
||||
一个简单的 HTML 实例,用于初步的了解效果:
|
||||
```html title='index.html'
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>仲夏夜之梦(notes.simengweb.com)</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>我的第一个标题</h1>
|
||||
<p>我的第一个段落。</p>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
小提示:可以将代码复制到 VsCode 中,然后使用 Live Server 插件就可以实时预览效果啦。
|
||||
|
||||
### HTML5 文档分析
|
||||
我们以前面的样例代码为例,来对 HTML 文档进行讲解
|
||||
|
||||
第一行:`<!DOCTYPE html>`,这是一个文档类型声明,用于告诉浏览器这是一个 HTML5 文档。
|
||||
|
||||
第二行:`<html>`,这是 HTML 文档的根元素,所有其他元素都必须嵌套在这个元素中,`<html>` 和 `</html>` 之间的内容就是文档的主体。
|
||||
|
||||
第三行到第六行:`<head>`,这是文档的头部元素,用于包含文档的元数据(比如标题、字符编码、外部资源引用等)。
|
||||
|
||||
第四行:`<meta charset="utf-8">`,这是一个元数据标签,用于指定文档的字符编码为 UTF-8。UTF-8 是一种常用的字符编码,能够表示世界上几乎所有的字符。如果不写的话可能会导致中文乱码的问题。
|
||||
|
||||
第五行:`<title>仲夏夜之梦(notes.simengweb.com)</title>`,这是文档的标题,会显示在浏览器的标题栏或标签页上。
|
||||
|
||||
第七行:`<body>`,这是文档的主体元素,用于包含文档的可见内容(比如文字、图片、按钮等),`<body>` 和 `</body>` 之间的内容就是文档的主体内容。
|
||||
|
||||
第八行:`<h1>我的第一个标题</h1>`,这是一个一级标题元素,用于表示文档的主要主题。`h1` 元素的内容会显示为较大的字体,通常用于页面的主标题。
|
||||
|
||||
第九行:`<p>我的第一个段落。</p>`,这是一个段落元素,用于表示文档中的一个段落。`p` 元素的内容会显示为普通的段落文本。
|
||||
|
||||
小提示:在浏览器中打开 F12 开启开发者工具,就可以查看和调试 HTML 文档啦。
|
||||
|
||||
## CSS3 基础知识讲解
|
||||
|
||||
CSS 是一种用来描述 HTML 文档“长什么样”的语言,专门负责网页的样式、排版与视觉效果。
|
||||
|
||||
CSS 也不是编程语言,而是一种“样式表”语言。它通过“选择器”找到 HTML 元素,再给它挂上一条或多条“声明”,告诉浏览器“这个元素应该是什么颜色、多大字号、放在哪里”。
|
||||
|
||||
一条 CSS 声明由“属性”和“值”组成,用冒号分隔,以分号结尾;多条声明放在花括号里,就组成了一条“样式规则”。
|
||||
|
||||
一个最简单的 CSS 示例,让页面里的标题变成红色、居中显示:
|
||||
::: code-tabs
|
||||
@tab index.html
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>仲夏夜之梦(notes.simengweb.com)</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>我的第一个标题</h1>
|
||||
<p>我的第一个段落。</p>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@tab style.css
|
||||
```css
|
||||
body {
|
||||
background-color:#d0e4fe;
|
||||
}
|
||||
h1 {
|
||||
color:orange;
|
||||
text-align:center;
|
||||
}
|
||||
p {
|
||||
font-family:"Times New Roman";
|
||||
font-size:20px;
|
||||
}
|
||||
```
|
||||
:::
|
||||
这里的 index.html 中需要添加一条语句,用于引入 CSS 样式表。
|
||||
```html
|
||||
<link rel="stylesheet" href="style.css">
|
||||
```
|
||||
然后通过浏览器打开 index.html 就可以看到效果啦。
|
||||
|
||||
### CSS 文档分析
|
||||
|
||||
我们以前面的样例代码为例,来对 CSS 文档进行讲解
|
||||
|
||||
第一到三行:`body { background-color:#d0e4fe; }`,这是一条针对 `<body>` 元素的样式规则。
|
||||
- `body` 是“选择器”,表示要把样式应用到整个网页主体。
|
||||
- `background-color` 是属性,用来设置背景颜色;`#d0e4fe` 是一个淡蓝色色值,因此整个页面会呈现淡蓝色背景。
|
||||
|
||||
第四行到第七行:`h1 { color:orange; text-align:center; }`,这是一条针对 `<h1>` 元素的样式规则。
|
||||
- `h1` 是“选择器”,对应 HTML 中的一级标题。
|
||||
- `color:orange;` 把标题文字设为橙色。
|
||||
- `text-align:center;` 让标题在水平方向上居中显示。
|
||||
|
||||
第八行到第十一行:`p { font-family:"Times New Roman"; font-size:20px; }`,这是一条针对 `<p>` 元素的样式规则。
|
||||
- `p` 是“选择器”,对应 HTML 中的段落。
|
||||
- `font-family:"Times New Roman";` 指定段落使用 Times New Roman 字体。
|
||||
- `font-size:20px;` 把段落文字大小设为 20 像素,让文字看起来更大、更清晰。
|
||||
|
||||
小提示:在 VsCode 中安装“Live Server”插件后,修改并保存 CSS 文件,浏览器会自动刷新,立即看到样式变化,方便调试。
|
||||
|
||||
## JavaScript 基础知识讲解
|
||||
|
||||
JavaScript(简称 JS)是让网页“动起来、能互动”的语言。它可以:
|
||||
- 响应用户操作(点击、输入、滚动等)
|
||||
- 修改页面内容与样式(增删节点、改文字/颜色)
|
||||
- 与服务器通信、处理数据与状态
|
||||
- 实现动画与复杂交互逻辑
|
||||
|
||||
下面用一个小示例,演示 JS 如何让页面产生交互效果:
|
||||
::: code-tabs
|
||||
@tab index.html
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>仲夏夜之梦(notes.simengweb.com)</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<!-- 样式写在外部 CSS 中 -->
|
||||
<!-- JavaScript 推荐放在 body 末尾,或使用 defer 属性 -->
|
||||
<!-- 这里在 body 末尾通过 src 引入外部脚本 -->
|
||||
</head>
|
||||
<body>
|
||||
<h1>我的第一个标题</h1>
|
||||
<p id="message">我的第一个段落。</p>
|
||||
|
||||
<button id="btn">点我试试</button>
|
||||
<input id="name" placeholder="输入你的名字" />
|
||||
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@tab script.js
|
||||
```js
|
||||
// 等页面元素加载完成后再执行(避免找不到节点)
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const msg = document.getElementById('message'); // 选择段落节点
|
||||
const btn = document.getElementById('btn'); // 选择按钮
|
||||
const nameInput = document.getElementById('name'); // 选择输入框
|
||||
|
||||
// 点击按钮,修改段落文本与颜色
|
||||
btn.addEventListener('click', () => {
|
||||
msg.textContent = '你点击了按钮!';
|
||||
msg.style.color = 'green';
|
||||
console.log('按钮被点击'); // 打开浏览器控制台可见
|
||||
});
|
||||
|
||||
// 输入时,实时更新欢迎语
|
||||
nameInput.addEventListener('input', (e) => {
|
||||
const name = e.target.value.trim();
|
||||
msg.textContent = name ? `你好,${name}!` : '我的第一个段落。';
|
||||
});
|
||||
});
|
||||
```
|
||||
:::
|
||||
|
||||
### JavaScript 文档分析
|
||||
我们以前面的样例代码为例,来对 JS 的关键点进行讲解:
|
||||
|
||||
- `<script src="script.js"></script>`:在 HTML 中通过 `script` 标签引入外部 JS 文件。常见放置位置是 `</body>` 之前,避免脚本执行时页面元素尚未加载。
|
||||
- `document.addEventListener('DOMContentLoaded', ...)`:等待文档结构加载完成再运行 JS,确保能获取到页面元素。
|
||||
- `document.getElementById('...')`:选择页面中的元素节点,便于后续读写或绑定事件。
|
||||
- `addEventListener('click'/'input', ...)`:给元素绑定事件监听器,描述“发生什么事时要做什么”。
|
||||
- `textContent / style`:修改文本与内联样式,从而即时改变页面显示效果。
|
||||
- `console.log(...)`:在开发者工具控制台输出调试信息,便于观察程序执行。
|
||||
|
||||
### 小提示
|
||||
- 打开浏览器开发者工具(F12),切到“Console”能查看 `console.log` 输出;在 “Elements”/“Inspector” 面板能查看并调试 DOM 结构与样式。
|
||||
- 在 VSCode 中使用 “Live Server”,保存 `script.js` 后浏览器会自动刷新,方便快速迭代。
|
||||
- 现代 JS 推荐使用 `const` 与 `let` 替代 `var`;多用箭头函数与模板字符串(如 `` `你好,${name}` ``)让代码更简洁。
|
||||
|
||||
到这里,我们已经分别了解了 HTML(结构)、CSS(样式)与 JavaScript(交互)三者如何协同工作。接下来可以尝试把它们组合起来,做一个小页面练手。
|
||||
|
||||
## 动手练习:小作业(只改 HTML/CSS,JS 已提供)
|
||||
|
||||
目标:做一个“欢迎卡片”,包含标题、说明文字、输入框与按钮。
|
||||
- 点击按钮时切换页面主题(浅色/深色),JS 会自动完成;
|
||||
- 输入名字时实时显示欢迎语;
|
||||
- 你只需要修改 HTML 和 CSS 来达到视觉与布局效果。
|
||||
|
||||
### 作业要求(验收标准)
|
||||
- 卡片居中显示,具有圆角、阴影与内边距;
|
||||
- 标题居中,段落有合适的行高与间距;
|
||||
- 按钮有悬停(hover)与按下(active)的视觉反馈;
|
||||
- 输入框获得焦点(focus)时有明显强调样式;
|
||||
- 在移动端(窄屏)不溢出,布局能自适应;
|
||||
- 深色主题下文字可读、对比度合理。提示:JS 会在 `<body>` 上切换 `theme-dark` 类,你可以在 CSS 中基于该类进行主题覆盖。
|
||||
|
||||
### 起步模板
|
||||
将以下三份代码保存为同目录下的 `index.html`、`style.css` 与 `script.js`,用 VSCode 的 Live Server 打开 `index.html` 进行预览。完成作业时,请只修改 HTML 和 CSS(保留 JS 的 id 与类名依赖)。
|
||||
|
||||
::: code-tabs
|
||||
@tab index.html
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>小作业:欢迎卡片</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="page">
|
||||
<div class="card" id="card">
|
||||
<h1 class="card__title">欢迎来到我的页面</h1>
|
||||
<p class="card__text" id="message">请点击按钮或输入你的名字</p>
|
||||
<div class="card__actions">
|
||||
<input id="name" class="input" placeholder="输入你的名字" />
|
||||
<button id="btn" class="btn btn--primary">点我切换主题</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="script.js" defer></script>
|
||||
<!-- 注意:JS 依赖 #message、#btn、#name 这几个 id,请不要改动它们的命名 -->
|
||||
<!-- 你可以新增或调整 class 名,或增删结构,来实现更好的视觉与布局 -->
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@tab style.css
|
||||
```css
|
||||
/* 目标:只通过 CSS 实现卡片的视觉与响应式,并支持深色主题 */
|
||||
/* 建议:使用 CSS 变量管理主题;在 .theme-dark 上覆盖变量 */
|
||||
|
||||
:root {
|
||||
--bg: #f7f9fc;
|
||||
--text: #222;
|
||||
--primary: #ff7a45; /* 可调整为你的品牌色 */
|
||||
--card-bg: #fff;
|
||||
--card-shadow: 0 10px 20px rgba(0,0,0,0.08);
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
font-family: system-ui, -apple-system, Segoe UI, Roboto, 'Helvetica Neue', Arial;
|
||||
}
|
||||
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.card {
|
||||
width: min(640px, 100%);
|
||||
background: var(--card-bg);
|
||||
border-radius: 16px;
|
||||
box-shadow: var(--card-shadow);
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.card__title {
|
||||
margin: 0 0 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.card__text {
|
||||
margin: 0 0 16px;
|
||||
line-height: 1.6;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.card__actions {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.input {
|
||||
padding: 10px 12px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
outline: none;
|
||||
min-width: 220px;
|
||||
}
|
||||
|
||||
.input:focus {
|
||||
border-color: var(--primary);
|
||||
box-shadow: 0 0 0 3px rgba(255, 122, 69, 0.2);
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 10px 16px;
|
||||
border: none;
|
||||
border-radius: 999px;
|
||||
cursor: pointer;
|
||||
transition: transform .08s ease, box-shadow .2s ease, background-color .2s ease;
|
||||
}
|
||||
|
||||
.btn--primary {
|
||||
background: var(--primary);
|
||||
color: #fff;
|
||||
box-shadow: 0 6px 12px rgba(255, 122, 69, .3);
|
||||
}
|
||||
|
||||
.btn--primary:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 8px 16px rgba(255, 122, 69, .4);
|
||||
}
|
||||
|
||||
.btn--primary:active {
|
||||
transform: translateY(0);
|
||||
box-shadow: 0 4px 8px rgba(255, 122, 69, .3);
|
||||
}
|
||||
|
||||
/* 任务:为深色主题定义样式。JS 会在 <body> 上切换 `.theme-dark` 类。*/
|
||||
body.theme-dark {
|
||||
--bg: #0f172a;
|
||||
--text: #e5e7eb;
|
||||
--primary: #60a5fa; /* 深色下可更柔和 */
|
||||
--card-bg: #1f2937;
|
||||
--card-shadow: none;
|
||||
}
|
||||
|
||||
/* 可选:为移动端优化 */
|
||||
@media (max-width: 480px) {
|
||||
.card { padding: 18px; }
|
||||
.input { min-width: 100%; }
|
||||
}
|
||||
```
|
||||
@tab script.js
|
||||
```js
|
||||
// JS 已提供:负责交互逻辑,切换主题与显示欢迎语
|
||||
// 你只需要改 HTML 和 CSS 即可达成作业要求
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const msg = document.getElementById('message');
|
||||
const btn = document.getElementById('btn');
|
||||
const nameInput = document.getElementById('name');
|
||||
|
||||
// 切换深色主题(在 <body> 上切换 theme-dark 类)
|
||||
btn.addEventListener('click', () => {
|
||||
document.body.classList.toggle('theme-dark');
|
||||
const dark = document.body.classList.contains('theme-dark');
|
||||
msg.textContent = dark ? '深色主题已开启' : '浅色主题已开启';
|
||||
});
|
||||
|
||||
// 实时欢迎语
|
||||
nameInput.addEventListener('input', (e) => {
|
||||
const name = e.target.value.trim();
|
||||
msg.textContent = name ? `你好,${name}!` : '请点击按钮或输入你的名字';
|
||||
});
|
||||
});
|
||||
```
|
||||
:::
|
||||
|
||||
### 提示与加分项
|
||||
- 可以用 `:root`+CSS 变量统一管理主题色,在 `.theme-dark` 中覆盖变量即可完成切换;
|
||||
- 尝试为按钮增加平滑过渡与阴影层次感;
|
||||
- 在移动端下让输入框占满一行,按钮在下一行显示;
|
||||
- 可自行优化字体、字号与间距,让视觉更加舒适;
|
||||
- 加分:实现卡片在深色主题下的微动效(例如背景色淡入)。
|
||||
|
||||
## 入门版(更简单,建议先做这个)
|
||||
|
||||
目标:做一个“欢迎卡片”,内容包括标题、说明文字、一个输入框和一个按钮。
|
||||
- 点击按钮时高亮卡片(JS 已完成,你只需让 `.card.highlight` 在 CSS 里更显眼)。
|
||||
- 输入名字时实时显示欢迎语(JS 已完成)。
|
||||
- 你只需要修改 HTML 和 CSS,让页面好看、布局合理即可。
|
||||
|
||||
验收标准(入门)
|
||||
- 卡片居中、圆角、阴影、内边距,整体观感舒适。
|
||||
- 按钮有 `hover/active` 反馈,输入框 `focus` 有强调样式。
|
||||
- 窄屏下不溢出,内容能自适应。
|
||||
|
||||
::: code-tabs
|
||||
@tab index.html
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>入门版小作业</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<!-- 保留以下 id:message / btn / name / card -->
|
||||
</head>
|
||||
<body>
|
||||
<div class="page">
|
||||
<div class="card" id="card">
|
||||
<h1>欢迎</h1>
|
||||
<p id="message">在输入框里写下你的名字</p>
|
||||
<input id="name" placeholder="输入你的名字">
|
||||
<button id="btn">高亮卡片</button>
|
||||
</div>
|
||||
</div>
|
||||
<script src="script.js"></script>
|
||||
<!-- 用 VSCode Live Server 打开 index.html 预览效果 -->
|
||||
<!-- 完成作业时,请只修改 HTML 和 CSS -->
|
||||
<!-- 你可以自由调整颜色、间距、字体与布局,使页面更美观 -->
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@tab style.css
|
||||
```css
|
||||
/* 极简样式:你可以在此基础上美化与调整 */
|
||||
body {
|
||||
margin: 0;
|
||||
background: #f5f7fa;
|
||||
font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial;
|
||||
}
|
||||
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.card {
|
||||
width: min(360px, 100%);
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 6px 12px rgba(0,0,0,0.08);
|
||||
padding: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
padding: 8px 10px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
outline: none;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
border-color: #1677ff;
|
||||
box-shadow: 0 0 0 2px rgba(22,119,255,.2);
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 8px 12px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
background: #1677ff;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:hover { filter: brightness(1.05); }
|
||||
button:active { filter: brightness(0.95); }
|
||||
|
||||
/* JS 点击按钮时会在卡片上切换 .highlight 类 */
|
||||
.card.highlight {
|
||||
background: #fffbe6; /* 浅黄色高亮 */
|
||||
box-shadow: 0 8px 16px rgba(0,0,0,0.10);
|
||||
}
|
||||
```
|
||||
@tab script.js
|
||||
```js
|
||||
// JS 已提供:负责简单交互。请只改 HTML/CSS。
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const msg = document.getElementById('message');
|
||||
const btn = document.getElementById('btn');
|
||||
const nameInput = document.getElementById('name');
|
||||
const card = document.getElementById('card');
|
||||
|
||||
// 实时欢迎语
|
||||
nameInput.addEventListener('input', (e) => {
|
||||
const name = e.target.value.trim();
|
||||
msg.textContent = name ? `你好,${name}!` : '在输入框里写下你的名字';
|
||||
});
|
||||
|
||||
// 切换卡片高亮
|
||||
btn.addEventListener('click', () => {
|
||||
card.classList.toggle('highlight');
|
||||
});
|
||||
});
|
||||
```
|
||||
:::
|
||||
|
||||
|
||||
@@ -0,0 +1,468 @@
|
||||
---
|
||||
title: html 列表与语义布局
|
||||
createTime: 2025/11/02 20:47:50
|
||||
permalink: /programming/web/basic-syntax/html-lists-and-semantic-layout/
|
||||
---
|
||||
## 四、列表(UL/OL/LI)
|
||||
|
||||
无序列表(圆点):
|
||||
```html title="index.html"
|
||||
<ul>
|
||||
<li>学习笔记</li>
|
||||
<li>工具推荐</li>
|
||||
<li>友情链接</li>
|
||||
</ul>
|
||||
```
|
||||
|
||||
有序列表(数字):
|
||||
```html title="index.html"
|
||||
<ol>
|
||||
<li>需求与原型</li>
|
||||
<li>API 设计</li>
|
||||
<li>联调与验收</li>
|
||||
</ol>
|
||||
```
|
||||
|
||||
**小案例:展示清单与步骤**
|
||||
::: code-tabs
|
||||
@tab index.html
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>列表案例</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<script defer src="app.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h2>我的清单</h2>
|
||||
<ul>
|
||||
<li>学习笔记</li>
|
||||
<li>工具推荐</li>
|
||||
<li>友情链接</li>
|
||||
</ul>
|
||||
<h2>项目步骤</h2>
|
||||
<ol>
|
||||
<li>需求与原型</li>
|
||||
<li>API 设计</li>
|
||||
<li>联调与验收</li>
|
||||
</ol>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@tab style.css
|
||||
```css
|
||||
ul, ol { margin: .5rem 0 1rem; padding-left: 1.5rem; }
|
||||
li { margin: .25rem 0; }
|
||||
```
|
||||
@tab app.js
|
||||
```js
|
||||
document.querySelectorAll('li').forEach(li => li.addEventListener('click', () => li.classList.toggle('done')));
|
||||
```
|
||||
:::
|
||||
|
||||
**小作业:做一个“今日任务清单”**
|
||||
::: code-tabs
|
||||
@tab index.html
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>今日任务清单</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>今天要做的事</h1>
|
||||
<ul>
|
||||
<li>阅读 30 分钟</li>
|
||||
<li>练习 1 个算法题</li>
|
||||
<li>整理房间</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@tab style.css
|
||||
```css
|
||||
body { font-family: system-ui; margin: 2rem; }
|
||||
li { cursor: pointer; }
|
||||
.done { text-decoration: line-through; color: #888; }
|
||||
```
|
||||
:::
|
||||
|
||||
## 五、语义化布局(Header/Nav/Main/Section/Article/Aside/Footer)
|
||||
|
||||
语义化标签让结构更清晰,搜索引擎更友好:
|
||||
```html title="index.html"
|
||||
<header>
|
||||
<h1>我的网站</h1>
|
||||
<nav>
|
||||
<a href="/blog/">博客</a>
|
||||
<a href="/notes/">笔记</a>
|
||||
</nav>
|
||||
<!-- 注意:更复杂的导航通常配合 CSS/JS 做响应式菜单 -->
|
||||
<!-- 小提示:块级容器的外层仍可使用 <div> 来做网格或栅格布局 -->
|
||||
<!-- 例如 <div class="container"> 包裹全站 -->
|
||||
<!-- 只是这些语义标签会让搜索引擎更理解结构 -->
|
||||
<!-- 语义标签与 <div> 并不冲突,可以配合使用 -->
|
||||
<!-- 选择语义标签能让你的 HTML 更“有含义”而非只是分区 -->
|
||||
<!-- 如果仅用于布局、无明确语义,用 <div> 即可 -->
|
||||
<!-- 这段说明旨在帮助你建立语义化与布局之间的直觉 -->
|
||||
<!-- 逐步养成好的结构化写法 -->
|
||||
<!-- 让内容更可维护,更易被机器理解 -->
|
||||
<!-- (继续往下看,还会介绍 Article/Section 等) -->
|
||||
```
|
||||
|
||||
> 语义化标签的要点:这些标签表达了“这是什么内容”,而不是“怎么显示”。更容易被搜索引擎和读屏工具理解。
|
||||
|
||||
**小案例:语义化布局入门**
|
||||
::: code-tabs
|
||||
@tab index.html
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>语义化布局案例</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<script defer src="app.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>我的网站</h1>
|
||||
<nav>
|
||||
<a href="#home">首页</a>
|
||||
<a href="#blog">博客</a>
|
||||
</nav>
|
||||
</header>
|
||||
<main>
|
||||
<section>
|
||||
<h2>最新文章</h2>
|
||||
<article>
|
||||
<h3>用语义标签改造你的页面</h3>
|
||||
<p>示例段落:用 header/nav/main/section/article/aside/footer 组织结构。</p>
|
||||
</article>
|
||||
</section>
|
||||
<aside>
|
||||
<h2>侧栏</h2>
|
||||
<p>这里可以放导航、标签云或广告位。</p>
|
||||
</aside>
|
||||
</main>
|
||||
<footer>© 2025 祀梦</footer>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@tab style.css
|
||||
```css
|
||||
body { font-family: system-ui; margin: 0; }
|
||||
header, footer { padding: 1rem 2rem; background: #f7f7f7; }
|
||||
nav { display: flex; gap: 1rem; }
|
||||
main { display: grid; grid-template-columns: 1fr 240px; gap: 1rem; padding: 1rem 2rem; }
|
||||
article { background: #fff; padding: 1rem; border: 1px solid #eee; border-radius: 8px; }
|
||||
aside { background: #fff; padding: 1rem; border: 1px solid #eee; border-radius: 8px; }
|
||||
```
|
||||
@tab app.js
|
||||
```js
|
||||
document.querySelectorAll('nav a').forEach(a => a.addEventListener('click', () => {
|
||||
document.querySelectorAll('nav a').forEach(x => x.classList.remove('active'));
|
||||
a.classList.add('active');
|
||||
}));
|
||||
```
|
||||
:::
|
||||
|
||||
**小作业:用语义标签搭一个博客首页**
|
||||
::: code-tabs
|
||||
@tab index.html
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>博客首页</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>博客名称</h1>
|
||||
<nav>
|
||||
<a href="#">首页</a>
|
||||
<a href="#">归档</a>
|
||||
<a href="#">关于</a>
|
||||
</nav>
|
||||
</header>
|
||||
<main>
|
||||
<section>
|
||||
<article>
|
||||
<h2>第一篇文章标题</h2>
|
||||
<p>摘要内容……</p>
|
||||
</article>
|
||||
<article>
|
||||
<h2>第二篇文章标题</h2>
|
||||
<p>摘要内容……</p>
|
||||
</article>
|
||||
</section>
|
||||
<aside>
|
||||
<h2>侧栏</h2>
|
||||
<p>分类、标签或个人简介。</p>
|
||||
</aside>
|
||||
</main>
|
||||
<footer>© 2025 你的名字</footer>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@tab style.css
|
||||
```css
|
||||
/* 与案例类似的栅格布局样式 */
|
||||
main { display: grid; grid-template-columns: 1fr 240px; gap: 1rem; padding: 1rem 2rem; }
|
||||
article { background: #fff; padding: 1rem; border: 1px solid #eee; border-radius: 8px; }
|
||||
aside { background: #fff; padding: 1rem; border: 1px solid #eee; border-radius: 8px; }
|
||||
```
|
||||
:::
|
||||
|
||||
## 六、表格(Table/TR/TH/TD)
|
||||
|
||||
```html title="index.html"
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>姓名</th>
|
||||
<th>职业</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>祀梦</td>
|
||||
<td>开发者</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
```
|
||||
小提示:表格样式通常用 CSS 来美化(边框、间距、对齐等)。
|
||||
|
||||
**小案例:信息表格**
|
||||
::: code-tabs
|
||||
@tab index.html
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>信息表格案例</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<script defer src="app.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>姓名</th><th>职业</th><th>城市</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>祀梦</td><td>开发者</td><td>上海</td></tr>
|
||||
<tr><td>小李</td><td>产品经理</td><td>杭州</td></tr>
|
||||
<tr><td>小王</td><td>设计师</td><td>北京</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@tab style.css
|
||||
```css
|
||||
table { border-collapse: collapse; width: 100%; }
|
||||
th, td { border: 1px solid #ddd; padding: .5rem .75rem; text-align: left; }
|
||||
thead th { background: #f7f7f7; }
|
||||
tbody tr:nth-child(odd) { background: #fafafa; }
|
||||
```
|
||||
@tab app.js
|
||||
```js
|
||||
document.querySelectorAll('tbody tr').forEach(tr => tr.addEventListener('click', () => tr.classList.toggle('highlight')));
|
||||
```
|
||||
:::
|
||||
|
||||
**小作业:制作“课程表”**
|
||||
::: code-tabs
|
||||
@tab index.html
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>课程表</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>时间</th><th>课程</th><th>教室</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>周一 9:00</td><td>数学</td><td>A101</td></tr>
|
||||
<tr><td>周三 14:00</td><td>英语</td><td>B302</td></tr>
|
||||
<tr><td>周五 10:00</td><td>计算机</td><td>C210</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@tab style.css
|
||||
```css
|
||||
table { border-collapse: collapse; width: 100%; }
|
||||
th, td { border: 1px solid #ddd; padding: .5rem .75rem; }
|
||||
thead th { background: #f0f0f0; }
|
||||
```
|
||||
:::
|
||||
|
||||
|
||||
## 七、媒体(Audio/Video/Source)
|
||||
|
||||
```html title="index.html"
|
||||
<audio src="bgm.mp3" controls loop></audio>
|
||||
|
||||
<video src="intro.mp4" controls width="480" poster="cover.jpg" muted></video>
|
||||
<!-- 常用属性:controls / autoplay / loop / muted / poster(封面) -->
|
||||
```
|
||||
|
||||
补充说明:
|
||||
- `controls` 提供播放控制;一般不建议隐藏,保证可用性。
|
||||
- `autoplay` 可能被浏览器限制;若需自动播放,通常需同时设置 `muted`。
|
||||
- `preload` 控制预加载策略(`none`/`metadata`/`auto`),根据页面性能需求选择。
|
||||
- `poster` 为视频未播放时的封面图;音频没有封面属性。
|
||||
- 使用 `<source>` 指定多种格式与 MIME 类型,提升兼容性:`<source src="xxx.mp4" type="video/mp4">`。
|
||||
|
||||
**小案例:嵌入音视频**
|
||||
::: code-tabs
|
||||
@tab index.html
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>媒体案例</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h2>背景音乐</h2>
|
||||
<audio src="bgm.mp3" controls loop></audio>
|
||||
<h2>介绍视频</h2>
|
||||
<video src="intro.mp4" controls width="480" poster="cover.jpg" muted></video>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@tab style.css
|
||||
```css
|
||||
video { display: block; margin-top: .5rem; }
|
||||
```
|
||||
:::
|
||||
|
||||
**小作业:添加一段你喜欢的音乐与视频**
|
||||
::: code-tabs
|
||||
@tab index.html
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>我的媒体</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<audio src="music.mp3" controls></audio>
|
||||
<video src="movie.mp4" controls width="480" poster="cover.jpg"></video>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@tab style.css
|
||||
```css
|
||||
audio, video { display: block; margin: .5rem 0; }
|
||||
```
|
||||
:::
|
||||
|
||||
|
||||
## 八、全局常用属性(任何标签几乎都能用)
|
||||
|
||||
- `id`:唯一标识,用于 JS/CSS 精确选择。
|
||||
- `class`:分组与样式选择(上一课已讲)。
|
||||
- `style`:内联样式(不推荐大量使用,建议写到 CSS 文件)。
|
||||
- `title`:悬停提示文字。
|
||||
- `data-*`:自定义数据属性(如 `data-user-id="42"`)。
|
||||
- `aria-*`:无障碍相关属性,帮助读屏工具理解(如 `aria-label`)。
|
||||
|
||||
**小案例:使用 id/class/data/title/aria**
|
||||
::: code-tabs
|
||||
@tab index.html
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>全局属性案例</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<script defer src="app.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<button id="likeBtn" class="btn" title="点赞一下" data-count="0" aria-label="点赞">👍 喜欢</button>
|
||||
<p id="msg" class="note" aria-live="polite">点击按钮试试。</p>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@tab style.css
|
||||
```css
|
||||
.btn { padding: .5rem .75rem; border: 1px solid #ccc; border-radius: 6px; background: #fff; }
|
||||
.note { color: #555; }
|
||||
```
|
||||
@tab app.js
|
||||
```js
|
||||
const btn = document.getElementById('likeBtn');
|
||||
const msg = document.getElementById('msg');
|
||||
btn.addEventListener('click', () => {
|
||||
const count = Number(btn.dataset.count || 0) + 1;
|
||||
btn.dataset.count = String(count);
|
||||
msg.textContent = `已点赞 ${count} 次`;
|
||||
});
|
||||
```
|
||||
:::
|
||||
|
||||
**小作业:做一个带计数的按钮**
|
||||
::: code-tabs
|
||||
@tab index.html
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>计数按钮</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<script defer src="app.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<button id="counter" class="btn" title="点击增加" data-count="0">点击我</button>
|
||||
<p id="status" class="note">当前计数:0</p>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@tab style.css
|
||||
```css
|
||||
.btn { padding: .5rem .75rem; border: 1px solid #ccc; border-radius: 6px; background: #fff; }
|
||||
.note { margin-top: .5rem; }
|
||||
```
|
||||
@tab app.js
|
||||
```js
|
||||
const counter = document.getElementById('counter');
|
||||
const statusEl = document.getElementById('status');
|
||||
counter.addEventListener('click', () => {
|
||||
const count = Number(counter.dataset.count || 0) + 1;
|
||||
counter.dataset.count = String(count);
|
||||
statusEl.textContent = `当前计数:${count}`;
|
||||
});
|
||||
```
|
||||
:::
|
||||
|
||||
## 结尾:先结构清晰,再上样式与交互
|
||||
|
||||
写网页像搭房子:先把房间(结构标签)安排好,再选家具颜色(CSS),最后加智能设备(JS)。
|
||||
|
||||
建议你先用这些常用标签做一个“个人名片页”,含标题、段落、头像图片、导航链接和一个简单表单。练熟后再加样式与交互。
|
||||
|
||||
**延伸阅读**:
|
||||
- HTML 规范与参考(MDN):https://developer.mozilla.org/en-US/docs/Web/HTML
|
||||
- 无障碍与语义化:https://developer.mozilla.org/en-US/docs/Glossary/Semantics
|
||||
424
docs/notes/programming/web/basic-syntax/html-tags-attributes.md
Normal file
424
docs/notes/programming/web/basic-syntax/html-tags-attributes.md
Normal file
@@ -0,0 +1,424 @@
|
||||
---
|
||||
title: HTML 常用标签与属性
|
||||
createTime: 2025/11/2 19:30:00
|
||||
permalink: /programming/web/basic-syntax/html-tags-attributes/
|
||||
---
|
||||
|
||||
## 文本与标题(H/P/Span/Strong/Em/Div)
|
||||
|
||||
**标题**:从重要到不重要,`<h1>` ~ `<h6>`。
|
||||
```html title="index.html"
|
||||
<h1>我的网站</h1>
|
||||
<h2>关于我</h2>
|
||||
<h3>联系方式</h3>
|
||||
```
|
||||
|
||||
### 认识div标签
|
||||
|
||||
**什么是 `<div>`?**
|
||||
|
||||
`<div>` 是 "division"(分区)的缩写,可以理解为网页中的"容器"或"盒子"。
|
||||
|
||||
想象一下搬家时的纸箱:
|
||||
|
||||
* 网页 = 整个房间
|
||||
* `<div>` = 一个个纸箱
|
||||
* 箱子里 = 可以放各种物品(文字、图片、按钮等)
|
||||
|
||||
### `<div>` 的基本特点
|
||||
|
||||
1. 块级元素
|
||||
`<div>` 是块级元素,这意味着:
|
||||
|
||||
* 默认会占据整行的宽度
|
||||
* 前后会自动换行
|
||||
* 就像段落一样,每个`<div>`都会从新的一行开始
|
||||
|
||||
**`<div>` 本身没有特定含义,它只是用来分组和布局。**
|
||||
|
||||
### 为什么要使用 `<div>`?
|
||||
|
||||
没有`<div>`的情况:
|
||||
```html title='index.html'
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>仲夏夜之梦</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>我的网站</h1>
|
||||
<p>欢迎来到我的个人网站!</p>
|
||||
<img src="photo.jpg" alt="我的照片">
|
||||
<p>这是我的个人介绍...</p>
|
||||
<button>联系我</button>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
所有元素都堆在一起,很难分别控制样式。
|
||||
|
||||
使用 `<div>` 的情况:
|
||||
```html title='index.html'
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>仲夏夜之梦</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<h1>我的网站</h1>
|
||||
<p>欢迎来到我的个人网站!</p>
|
||||
</div>
|
||||
<div class="content">
|
||||
<img src="photo.jpg" alt="我的照片">
|
||||
<p>这是我的个人介绍...</p>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<button>联系我</button>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
这样我就可以分别控制每个部分的样式啦!
|
||||
|
||||
这个时候又有聪明的小朋友问了:这个class是什么呀?难道说?!是**起的名字!!**
|
||||
|
||||
太好了,恭喜你答对了,那么我们为什么要用class呢?
|
||||
|
||||
### Class
|
||||
|
||||
Class 可以理解为给 HTML 元素起的"组名"或"类别名",让 CSS 能够精确地找到并美化特定的元素。
|
||||
|
||||
想象一个学校:
|
||||
* HTML 元素 = 学生
|
||||
* Class = 学生的身份(如"三年级一班"、"篮球队员")
|
||||
* CSS = 老师,根据身份给学生安排不同的任务和服装
|
||||
|
||||
class基本用法此处就不举例了,详情参照上面的代码。
|
||||
|
||||
如果没有class的情况:
|
||||
```html title='index.html'
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>仲夏夜之梦</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>我的网站</h1>
|
||||
<p>普通段落</p>
|
||||
<p>个人介绍</p>
|
||||
<p>重要提示</p>
|
||||
<button>普通按钮</button>
|
||||
<button>重要按钮</button>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
如果我们想给"重要提示"和"重要按钮"设置特殊样式,很难精确选择!像之前我教的一样css直接用p或者h1来选择的话就无法区分具体每一段的区别了。
|
||||
|
||||
这时候就可以用class了!
|
||||
::: code-tabs
|
||||
@tab index.html
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>仲夏夜之梦</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>我的网站</h1>
|
||||
<p class="normal">普通段落</p>
|
||||
<p class="intro">个人介绍</p>
|
||||
<p class="warning">重要提示</p>
|
||||
<button class="normal-btn">普通按钮</button>
|
||||
<button class="important-btn">重要按钮</button>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@tab style.css
|
||||
```css
|
||||
.warning {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
.important-btn {
|
||||
background-color: red;
|
||||
color: white;
|
||||
}
|
||||
```
|
||||
:::
|
||||
**现在自己动手尝试一下**
|
||||
|
||||
## 动手练习:小作业
|
||||
|
||||
运用所学的 HTML 和 CSS 知识,创建一个美观的个人名片页面。不确定的时候翻翻文档
|
||||
|
||||
```html title='index.html'
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<!-- 在这里添加字符编码和标题 -->
|
||||
</head>
|
||||
<body>
|
||||
<!-- 创建一个名片容器 div,class 为 "card" -->
|
||||
|
||||
<!-- 在卡片内部分为三个区域: -->
|
||||
|
||||
<!-- 1. 头部区域:包含姓名和职位 -->
|
||||
<div class="card-header">
|
||||
<!-- 添加 h1 标题显示你的姓名 -->
|
||||
<!-- 添加 p 段落显示你的职位或专业 -->
|
||||
</div>
|
||||
|
||||
<!-- 2. 主体区域:包含联系信息 -->
|
||||
<div class="card-body">
|
||||
<!-- 添加至少3个联系信息,使用 p 标签 -->
|
||||
<!-- 例如:电话、邮箱、地址等 -->
|
||||
</div>
|
||||
|
||||
<!-- 3. 底部区域:包含个人简介 -->
|
||||
<div class="card-footer">
|
||||
<!-- 添加一个个人简介段落 -->
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
css样式自定,发挥自己的创作力,创建一个独特的个人名片页面。
|
||||
|
||||
**段落与换行**:
|
||||
```html title="index.html"
|
||||
<p>这是一个段落,里面可以有<strong>加粗</strong>和<em>强调</em>。</p>
|
||||
<p>这是另一个段落。<br>需要换行时用 <code><br></code>。</p>
|
||||
<hr> <!-- 水平分割线 -->
|
||||
```
|
||||
|
||||
**行内 vs 块级**:
|
||||
- `<div>` 是块级元素(换行占整行),用于分区布局;
|
||||
- `<span>` 是行内元素(不换行),用于强调局部文字。
|
||||
|
||||
使用建议与解释:
|
||||
- 语义优先:`<strong>` 表示“语义上的重点”,`<b>` 仅表示“加粗外观”;`<em>` 表示“语气强调”,`<i>` 仅表示“斜体外观”。优先使用语义标签,样式交给 CSS。
|
||||
- 标题层级:通常一个页面只有一个 `<h1>`,下面按层级组织为 `<h2>/<h3>...`。不要为求大小随意跳级或用标题替代普通文本。
|
||||
- 段落与换行:换行请优先使用分段(`<p>`),只有在同段内需要视觉换行时使用 `<br>`。`<hr>` 适合用于内容分隔或主题切换。
|
||||
|
||||
**小案例:文本与标题**
|
||||
::: code-tabs
|
||||
@tab index.html
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>文本与标题案例</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>我的网站</h1>
|
||||
<h2>关于我</h2>
|
||||
<p>我是一名<strong>前端开发者</strong>,喜欢<em>简洁的设计</em>与清晰的结构。</p>
|
||||
<hr>
|
||||
<h3>联系方式</h3>
|
||||
<p>Email: hello@example.com</p>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@tab style.css
|
||||
```css
|
||||
body { font-family: system-ui; margin: 2rem; }
|
||||
h1 { font-size: 2rem; margin-bottom: .5rem; }
|
||||
h2 { margin-top: 1.5rem; }
|
||||
p { margin: .5rem 0; }
|
||||
```
|
||||
:::
|
||||
|
||||
**小作业:写一段个人简介**
|
||||
::: code-tabs
|
||||
@tab index.html
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>个人简介</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>你的名字</h1>
|
||||
<h2>一句话介绍</h2>
|
||||
<p>用两段文字,分别写你现在在做什么、你感兴趣的方向。</p>
|
||||
<p>使用 <strong>strong</strong> 与 <em>em</em> 做重点强调。</p>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@tab style.css
|
||||
```css
|
||||
body { font-family: system-ui; margin: 2rem; line-height: 1.8; }
|
||||
p { max-width: 60ch; }
|
||||
```
|
||||
:::
|
||||
|
||||
## 三、链接与图片(A/IMG)
|
||||
|
||||
### 什么是 `<img>` 标签
|
||||
|
||||
`<img>` 标签用于在网页中插入图片,它是自闭合标签(不需要结束标签)。
|
||||
|
||||
### `<img>` 标签的基本属性
|
||||
|
||||
* src:指定图片的路径(必填)
|
||||
* alt:指定图片的替代文本(必填,用于图片加载失败时显示)
|
||||
* width:指定图片的宽度(可选)
|
||||
* height:指定图片的高度(可选)
|
||||
|
||||
基本语法:
|
||||
```html title='index.html'
|
||||
<img src="photo.jpg" alt="我的照片" width="200" height="300">
|
||||
```
|
||||
|
||||
### HTML 超链接
|
||||
|
||||
HTML 链接(Anchor)是网页之间跳转的核心部分。
|
||||
|
||||
HTML 使用链接与网络上的另一个文档相连。
|
||||
|
||||
HTML中的链接是一种用于在不同网页之间导航的元素。
|
||||
|
||||
链接通常用于将一个网页与另一个网页或资源(如文档、图像、音频文件等)相关联。
|
||||
|
||||
链接允许用户在浏览网页时单击文本或图像来跳转到其他位置,从而实现网页之间的互联。
|
||||
|
||||
HTML 链接 通过 `<a>` 标签创建,通常用于将用户从一个页面导航到另一个页面、从一个部分跳转到页面中的另一个部分、下载文件、打开电子邮件应用程序或执行 JavaScript 函数等。
|
||||
|
||||
超链接可以是一个字,一个词,或者一组词,也可以是一幅图像,可以点击这些内容来跳转到新的文档或者当前文档中的某个部分。
|
||||
|
||||
当把鼠标指针移动到网页中的某个链接上时,箭头会变为**一只小手**。
|
||||
|
||||
## `<a>` 标签的基本属性
|
||||
|
||||
* href:指定链接的目标 URL(必填)
|
||||
* target:指定链接在何处打开(可选)
|
||||
* _blank:在新窗口或标签页中打开链接
|
||||
* _self:在当前窗口或标签页中打开链接(默认)
|
||||
* _parent:在父框架中打开链接
|
||||
* _top:在顶部框架中打开链接
|
||||
|
||||
基本语法:
|
||||
```html title='index.html'
|
||||
<a href="https://www.example.com">链接文本</a>
|
||||
```
|
||||
- `<a>` 标签:定义了一个超链接(anchor)。它是 HTML 中用来创建可点击链接的主要标签。
|
||||
- href 属性:指定目标 URL,当点击链接时,浏览器将导航到此 URL。
|
||||
|
||||
**这里还有一个target 属性**:
|
||||
- _blank:在新窗口或标签页中打开链接
|
||||
- _self:在当前窗口或标签页中打开链接(默认)
|
||||
- _parent:在父框架中打开链接
|
||||
- _top:在顶部框架中打开链接
|
||||
|
||||
```html title='index.html'
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>target属性示例</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>target属性示例</h2>
|
||||
|
||||
<!-- 在当前窗口打开(默认) -->
|
||||
<a href="https://www.baidu.com" target="_self">当前窗口打开</a>
|
||||
|
||||
<!-- 在新窗口打开 -->
|
||||
<a href="https://www.baidu.com" target="_blank">新窗口打开</a>
|
||||
|
||||
<!-- 在父窗口打开 -->
|
||||
<a href="https://www.baidu.com" target="_parent">父窗口打开</a>
|
||||
|
||||
<!-- 建议:新窗口打开外部链接 -->
|
||||
<a href="https://www.example.com" target="_blank" rel="noopener">
|
||||
外部网站(安全的新窗口)
|
||||
</a>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
复制代码到自己的html文件中,尝试一下不同的target属性值。
|
||||
|
||||
常用属性:
|
||||
- `href`:目标地址;
|
||||
- `target="_blank"`:新窗口打开;
|
||||
- `rel="noopener"`:安全与性能(避免旧窗口被新页面控制)。
|
||||
|
||||
补充说明:
|
||||
- 链接安全:外链新窗口打开时同时设置 `rel="noopener"` 或 `rel="noreferrer"`,避免安全与性能问题。
|
||||
- 图片可使用 `loading="lazy"` 懒加载,减少首屏资源压力;`alt` 请写出图片用途或内容摘要。
|
||||
- 设定 `width/height` 可以预留占位,减少页面布局抖动(CLS)。复杂场景可考虑 `<picture>` + `<source>` 做响应式图片。
|
||||
- 与图片相关的配套标签:`<figure>` + `<figcaption>` 用于图片与说明文字的组合。
|
||||
|
||||
**小案例:链接与图片**
|
||||
::: code-tabs
|
||||
@tab index.html
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>链接与图片案例</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<a href="/" >首页</a>
|
||||
<a href="https://developer.mozilla.org/" target="_blank" rel="noopener">MDN</a>
|
||||
</nav>
|
||||
<img src="avatar.jpg" alt="我的头像" width="160" height="160">
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@tab style.css
|
||||
```css
|
||||
nav { display: flex; gap: 1rem; margin-bottom: 1rem; }
|
||||
nav a { color: #06c; text-decoration: none; }
|
||||
nav a:hover { text-decoration: underline; }
|
||||
img { border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,.1); }
|
||||
```
|
||||
:::
|
||||
|
||||
**小作业:做一个“友链”与头像区块**
|
||||
::: code-tabs
|
||||
@tab index.html
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>友链与头像</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<section>
|
||||
<h2>友情链接</h2>
|
||||
<p>
|
||||
<a href="https://notes.simengweb.com" target="_blank" rel="noopener">祀梦笔记</a>
|
||||
·
|
||||
<a href="https://vuejs.org/" target="_blank" rel="noopener">Vue.js</a>
|
||||
</p>
|
||||
</section>
|
||||
<section>
|
||||
<h2>头像</h2>
|
||||
<img src="avatar.jpg" alt="你的头像" width="160" height="160">
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@tab style.css
|
||||
```css
|
||||
section { margin-bottom: 1rem; }
|
||||
img { border: 2px solid #eee; border-radius: 50%; }
|
||||
```
|
||||
:::
|
||||
|
||||
606
docs/notes/programming/web/basic-syntax/javascript-basics.md
Normal file
606
docs/notes/programming/web/basic-syntax/javascript-basics.md
Normal file
@@ -0,0 +1,606 @@
|
||||
---
|
||||
title: JavaScript 基础知识
|
||||
createTime: 2025/11/2 21:30:00
|
||||
permalink: /programming/web/basic-syntax/javascript-basics/
|
||||
---
|
||||
|
||||
## JavaScript 是什么?
|
||||
|
||||
JavaScript 是一种广泛用于网页开发的脚本语言,它使网页能够实现交互式功能。与 HTML(负责结构)和 CSS(负责样式)不同,JavaScript 专注于**行为**,可以让网页变得动态和响应式。
|
||||
|
||||
|
||||
## 第一个 JavaScript 程序
|
||||
|
||||
JavaScript 代码可以直接写在 HTML 文件中,通常放在 `<body>` 标签的底部,使用 `<script>` 标签包裹。
|
||||
|
||||
```html title="index.html"
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>我的第一个 JavaScript 程序</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>你好,世界!</h1>
|
||||
|
||||
<script>
|
||||
// 这是注释,不会被执行
|
||||
console.log('Hello, JavaScript!'); // 在控制台输出文本
|
||||
alert('欢迎学习 JavaScript!'); // 弹出提示框
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
**提示**:你可以在浏览器中按下 F12 打开开发者工具,然后切换到 "Console" 标签查看 `console.log()` 的输出。
|
||||
|
||||
`console.log()` 是 JavaScript 中最常用、最重要的调试工具,可以说是每个开发者的"最佳朋友"!
|
||||
|
||||
### 基本输出 ###
|
||||
|
||||
```javascript
|
||||
// 输出字符串
|
||||
console.log("Hello World!");
|
||||
|
||||
// 输出变量
|
||||
const name = "小明";
|
||||
console.log(name);
|
||||
|
||||
// 输出多个值
|
||||
const age = 18;
|
||||
const isStudent = true;
|
||||
console.log("学生信息:", name, age, isStudent);
|
||||
```
|
||||
|
||||
### 输出不同类型的数据 ###
|
||||
|
||||
```javascript
|
||||
// 各种数据类型
|
||||
console.log("字符串:", "Hello");
|
||||
console.log("数字:", 42);
|
||||
console.log("布尔值:", true);
|
||||
console.log("数组:", [1, 2, 3]);
|
||||
console.log("对象:", {name: "李华", age: 20});
|
||||
console.log("函数:", function() {});
|
||||
console.log("undefined:", undefined);
|
||||
console.log("null:", null);
|
||||
```
|
||||
|
||||
### 字符串插值 ###
|
||||
|
||||
```javascript
|
||||
const userName = "张三";
|
||||
const userAge = 25;
|
||||
const score = 95.5;
|
||||
|
||||
// 传统方式
|
||||
console.log("用户 " + userName + " 年龄 " + userAge + " 分数 " + score);
|
||||
|
||||
// 模板字符串(推荐)
|
||||
console.log(`用户 ${userName} 年龄 ${userAge} 分数 ${score}`);
|
||||
|
||||
// 带表达式的插值
|
||||
console.log(`${userName} 是 ${userAge >= 18 ? "成年人" : "未成年人"}`);
|
||||
```
|
||||
|
||||
### 格式化输出 ###
|
||||
|
||||
```javascript
|
||||
const product = {
|
||||
name: "笔记本电脑",
|
||||
price: 5999,
|
||||
brand: "Dell",
|
||||
inStock: true
|
||||
};
|
||||
|
||||
// %s - 字符串
|
||||
console.log("产品名称: %s", product.name);
|
||||
|
||||
// %d - 数字
|
||||
console.log("价格: %d 元", product.price);
|
||||
|
||||
// %f - 浮点数
|
||||
console.log("折扣价: %f", product.price * 0.9);
|
||||
|
||||
// %o - 对象
|
||||
console.log("完整产品信息: %o", product);
|
||||
|
||||
// %c - CSS样式
|
||||
console.log("%c重要信息!", "color: red; font-size: 20px; font-weight: bold;");
|
||||
```
|
||||
|
||||
## JavaScript 变量
|
||||
|
||||
变量是用来存储信息的容器。在 JavaScript 中,我们使用 `let`、`const` 或 `var` 关键字来声明变量。
|
||||
|
||||
### 变量声明方式
|
||||
|
||||
```javascript
|
||||
// 使用 let 声明可变变量
|
||||
let name = "小明";
|
||||
name = "小红"; // 可以修改
|
||||
|
||||
// 使用 const 声明常量(不可变)
|
||||
const PI = 3.14159;
|
||||
// PI = 3.14; // 错误!常量不能修改
|
||||
|
||||
// 使用 var 声明变量(旧方式,现在推荐使用 let 和 const)
|
||||
var age = 25;
|
||||
```
|
||||
|
||||
**注意**:
|
||||
- 使用 `let` 声明的变量可以重新赋值
|
||||
- 使用 `const` 声明的变量不能重新赋值(常量)
|
||||
- 尽量避免使用 `var`,因为它有一些奇怪的作用域规则
|
||||
|
||||
|
||||
## 数据类型
|
||||
|
||||
JavaScript 有几种基本数据类型:
|
||||
|
||||
### 1. 字符串(String)
|
||||
|
||||
用于表示文本,可以使用单引号或双引号。
|
||||
|
||||
```javascript
|
||||
const greeting = "你好";
|
||||
const name = 'JavaScript';
|
||||
const message = `${greeting}, ${name}!`; // 使用模板字符串(ES6 特性)
|
||||
console.log(message); // 输出:你好, JavaScript!
|
||||
```
|
||||
|
||||
### 2. 数字(Number)
|
||||
|
||||
用于表示数值。
|
||||
|
||||
```javascript
|
||||
const age = 25;
|
||||
const price = 99.99;
|
||||
const PI = 3.14159;
|
||||
```
|
||||
|
||||
### 3. 布尔值(Boolean)
|
||||
|
||||
用于表示真或假,只有两个值:`true` 和 `false`。
|
||||
|
||||
```javascript
|
||||
const isStudent = true;
|
||||
const hasGraduated = false;
|
||||
```
|
||||
|
||||
### 4. 数组(Array)
|
||||
|
||||
用于存储多个值的集合。
|
||||
|
||||
```javascript
|
||||
const fruits = ["苹果", "香蕉", "橙子"];
|
||||
console.log(fruits[0]); // 输出:苹果(数组索引从0开始)
|
||||
|
||||
// 添加元素
|
||||
fruits.push("葡萄");
|
||||
console.log(fruits); // 输出:["苹果", "香蕉", "橙子", "葡萄"]
|
||||
```
|
||||
|
||||
### 5. 对象(Object)
|
||||
|
||||
用于存储键值对集合。
|
||||
|
||||
```javascript
|
||||
const person = {
|
||||
name: "小明",
|
||||
age: 25,
|
||||
isStudent: true,
|
||||
greet: function() {
|
||||
console.log(`你好,我是${this.name}!`);
|
||||
}
|
||||
};
|
||||
|
||||
console.log(person.name); // 输出:小明
|
||||
person.greet(); // 输出:你好,我是小明!
|
||||
```
|
||||
|
||||
## 运算符
|
||||
|
||||
### 算术运算符
|
||||
|
||||
```javascript
|
||||
const a = 10;
|
||||
const b = 5;
|
||||
|
||||
console.log(a + b); // 15 加法
|
||||
console.log(a - b); // 5 减法
|
||||
console.log(a * b); // 50 乘法
|
||||
console.log(a / b); // 2 除法
|
||||
console.log(a % b); // 0 取余
|
||||
console.log(a ** b); // 100000 幂运算(ES6)
|
||||
```
|
||||
|
||||
### 赋值运算符
|
||||
|
||||
```javascript
|
||||
const x = 10;
|
||||
|
||||
x += 5; // 等同于 x = x + 5
|
||||
console.log(x); // 15
|
||||
|
||||
x -= 3; // 等同于 x = x - 3
|
||||
console.log(x); // 12
|
||||
```
|
||||
|
||||
### 比较运算符
|
||||
|
||||
```javascript
|
||||
const a = 10;
|
||||
const b = 5;
|
||||
|
||||
console.log(a > b); // true
|
||||
console.log(a < b); // false
|
||||
console.log(a >= b); // true
|
||||
console.log(a <= b); // false
|
||||
console.log(a === b); // false(严格相等,比较值和类型)
|
||||
console.log(a == b); // false(宽松相等,只比较值)
|
||||
console.log(a !== b); // true(严格不相等)
|
||||
```
|
||||
|
||||
## 条件语句
|
||||
|
||||
### if 语句
|
||||
|
||||
```javascript
|
||||
const age = 18;
|
||||
|
||||
if (age >= 18) {
|
||||
console.log("你已经成年了!");
|
||||
} else if (age >= 13) {
|
||||
console.log("你是青少年。");
|
||||
} else {
|
||||
console.log("你还是个孩子。");
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## 循环
|
||||
|
||||
### for 循环
|
||||
|
||||
```javascript
|
||||
// 打印1到5
|
||||
for (const i = 1; i <= 5; i++) {
|
||||
console.log(i);
|
||||
}
|
||||
|
||||
// 遍历数组
|
||||
const fruits = ["苹果", "香蕉", "橙子"];
|
||||
for (const i = 0; i < fruits.length; i++) {
|
||||
console.log(fruits[i]);
|
||||
}
|
||||
|
||||
// 使用 for...of 遍历(ES6)
|
||||
for (const fruit of fruits) {
|
||||
console.log(fruit);
|
||||
}
|
||||
```
|
||||
|
||||
### while 循环
|
||||
|
||||
```javascript
|
||||
const count = 1;
|
||||
while (count <= 5) {
|
||||
console.log(count);
|
||||
count++;
|
||||
}
|
||||
```
|
||||
|
||||
## 函数
|
||||
|
||||
函数是一段可重复使用的代码块,可以接受输入(参数),执行操作,并返回输出(返回值)。
|
||||
|
||||
### 函数声明
|
||||
|
||||
```javascript
|
||||
function greet(name) {
|
||||
return `你好,${name}!`;
|
||||
}
|
||||
|
||||
const message = greet("小明");
|
||||
console.log(message); // 输出:你好,小明!
|
||||
```
|
||||
|
||||
格式如下
|
||||
|
||||
```javascript
|
||||
function 函数名(参数1, 参数2, ...参数N) {
|
||||
// 函数体:要执行的代码
|
||||
return 返回值; // 可选
|
||||
}
|
||||
```
|
||||
|
||||
### 箭头函数(ES6)
|
||||
|
||||
```javascript
|
||||
const sum = (a, b) => {
|
||||
return a + b;
|
||||
};
|
||||
|
||||
// 简化写法(当只有一行返回语句时)
|
||||
const multiply = (a, b) => a * b;
|
||||
|
||||
console.log(sum(3, 4)); // 7
|
||||
console.log(multiply(3, 4)); // 12
|
||||
```
|
||||
|
||||
## DOM 操作
|
||||
|
||||
DOM(文档对象模型)是 HTML 和 XML 文档的编程接口。JavaScript 可以通过 DOM 来操作网页元素。
|
||||
|
||||
### 选择元素
|
||||
|
||||
```javascript
|
||||
// 通过 id 选择元素
|
||||
const title = document.getElementById("title");
|
||||
|
||||
// 通过 class 选择元素(返回元素集合)
|
||||
const items = document.getElementsByClassName("item");
|
||||
|
||||
// 通过标签名选择元素
|
||||
const paragraphs = document.getElementsByTagName("p");
|
||||
|
||||
// 通过 CSS 选择器选择元素(ES5+)
|
||||
const header = document.querySelector("header"); // 选择第一个匹配的元素
|
||||
const allLinks = document.querySelectorAll("a"); // 选择所有匹配的元素
|
||||
```
|
||||
|
||||
### 修改元素内容
|
||||
|
||||
```javascript
|
||||
// 修改文本内容
|
||||
const title = document.getElementById("title");
|
||||
title.textContent = "新标题";
|
||||
|
||||
// 修改 HTML 内容
|
||||
title.innerHTML = "<strong>加粗的新标题</strong>";
|
||||
```
|
||||
|
||||
### 修改元素样式
|
||||
|
||||
```javascript
|
||||
const element = document.getElementById("box");
|
||||
element.style.color = "red";
|
||||
element.style.fontSize = "20px";
|
||||
element.style.backgroundColor = "#f0f0f0";
|
||||
```
|
||||
|
||||
### 添加事件监听器
|
||||
|
||||
```javascript
|
||||
const button = document.getElementById("myButton");
|
||||
|
||||
button.addEventListener("click", function() {
|
||||
console.log("按钮被点击了!");
|
||||
alert("你好,欢迎使用!");
|
||||
});
|
||||
```
|
||||
|
||||
## 小案例:交互式计算器
|
||||
|
||||
下面是一个简单的交互式计算器示例,演示如何结合 HTML、CSS 和 JavaScript。
|
||||
|
||||
::: code-tabs
|
||||
@tab index.html
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>简易计算器</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="calculator">
|
||||
<h2>简易计算器</h2>
|
||||
<input type="number" id="num1" placeholder="输入第一个数字">
|
||||
<select id="operation">
|
||||
<option value="add">+</option>
|
||||
<option value="subtract">-</option>
|
||||
<option value="multiply">×</option>
|
||||
<option value="divide">÷</option>
|
||||
</select>
|
||||
<input type="number" id="num2" placeholder="输入第二个数字">
|
||||
<button id="calculate">计算</button>
|
||||
<div id="result">结果将显示在这里</div>
|
||||
</div>
|
||||
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@tab style.css
|
||||
```css
|
||||
.calculator {
|
||||
max-width: 300px;
|
||||
margin: 2rem auto;
|
||||
padding: 1.5rem;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
font-family: system-ui;
|
||||
}
|
||||
|
||||
input, select, button {
|
||||
margin: 0.5rem 0;
|
||||
padding: 0.5rem;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
button {
|
||||
background: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background: #0056b3;
|
||||
}
|
||||
|
||||
#result {
|
||||
margin-top: 1rem;
|
||||
padding: 1rem;
|
||||
background: #f8f9fa;
|
||||
border-radius: 4px;
|
||||
}
|
||||
```
|
||||
@tab script.js
|
||||
```javascript
|
||||
// 获取DOM元素
|
||||
const num1Input = document.getElementById('num1');
|
||||
const num2Input = document.getElementById('num2');
|
||||
const operationSelect = document.getElementById('operation');
|
||||
const calculateButton = document.getElementById('calculate');
|
||||
const resultDiv = document.getElementById('result');
|
||||
|
||||
// 添加点击事件监听器
|
||||
calculateButton.addEventListener('click', function() {
|
||||
// 获取输入值
|
||||
const num1 = parseFloat(num1Input.value);
|
||||
const num2 = parseFloat(num2Input.value);
|
||||
const operation = operationSelect.value;
|
||||
const result;
|
||||
|
||||
// 检查输入是否有效
|
||||
if (isNaN(num1) || isNaN(num2)) {
|
||||
resultDiv.textContent = '请输入有效的数字!';
|
||||
return;
|
||||
}
|
||||
|
||||
// 执行计算
|
||||
switch (operation) {
|
||||
case 'add':
|
||||
result = num1 + num2;
|
||||
break;
|
||||
case 'subtract':
|
||||
result = num1 - num2;
|
||||
break;
|
||||
case 'multiply':
|
||||
result = num1 * num2;
|
||||
break;
|
||||
case 'divide':
|
||||
// 检查除数是否为0
|
||||
if (num2 === 0) {
|
||||
resultDiv.textContent = '除数不能为0!';
|
||||
return;
|
||||
}
|
||||
result = num1 / num2;
|
||||
break;
|
||||
}
|
||||
|
||||
// 显示结果
|
||||
resultDiv.textContent = `计算结果:${result}`;
|
||||
});
|
||||
```
|
||||
:::
|
||||
|
||||
## JavaScript 的异步编程
|
||||
|
||||
JavaScript 是单线程的,但它可以通过异步编程模型来处理耗时操作,如网络请求、定时器等。
|
||||
|
||||
### setTimeout 和 setInterval
|
||||
|
||||
```javascript
|
||||
// setTimeout - 延迟执行一次
|
||||
setTimeout(function() {
|
||||
console.log('2秒后执行');
|
||||
}, 2000);
|
||||
|
||||
// setInterval - 定期重复执行
|
||||
const count = 0;
|
||||
const timer = setInterval(function() {
|
||||
count++;
|
||||
console.log(`执行第 ${count} 次`);
|
||||
|
||||
if (count >= 5) {
|
||||
clearInterval(timer); // 清除定时器
|
||||
console.log('定时器已停止');
|
||||
}
|
||||
}, 1000);
|
||||
```
|
||||
|
||||
### Promise(ES6)
|
||||
|
||||
Promise 是异步编程的一种解决方案,用于处理异步操作。
|
||||
|
||||
```javascript
|
||||
// 创建一个Promise
|
||||
const fetchData = new Promise((resolve, reject) => {
|
||||
// 模拟网络请求
|
||||
setTimeout(() => {
|
||||
const success = true;
|
||||
if (success) {
|
||||
resolve('数据获取成功');
|
||||
} else {
|
||||
reject('数据获取失败');
|
||||
}
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
// 使用Promise
|
||||
fetchData
|
||||
.then(data => {
|
||||
console.log(data);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
});
|
||||
```
|
||||
|
||||
## 常见错误和调试技巧
|
||||
|
||||
### 常见错误
|
||||
|
||||
1. **语法错误**:代码不符合 JavaScript 语法规则
|
||||
2. **引用错误**:使用了未定义的变量或函数
|
||||
3. **类型错误**:对错误类型的值进行操作
|
||||
4. **范围错误**:数值超出有效范围
|
||||
|
||||
### 调试技巧
|
||||
|
||||
1. **使用 console.log()**:在控制台输出变量值或执行流程
|
||||
2. **使用断点**:在浏览器开发者工具中设置断点,逐步执行代码
|
||||
3. **检查错误信息**:仔细阅读错误提示,找出问题所在
|
||||
4. **检查变量类型**:使用 `typeof` 操作符检查变量类型
|
||||
|
||||
```javascript
|
||||
console.log(typeof "hello"); // "string"
|
||||
console.log(typeof 42); // "number"
|
||||
console.log(typeof true); // "boolean"
|
||||
console.log(typeof {}); // "object"
|
||||
console.log(typeof []); // "object"(数组也是对象的一种)
|
||||
```
|
||||
|
||||
## 实践练习
|
||||
|
||||
### 练习1:创建一个简单的待办事项列表
|
||||
|
||||
使用 HTML、CSS 和 JavaScript 创建一个待办事项列表,包含添加、删除和标记完成功能。
|
||||
|
||||
提示:
|
||||
- 使用数组存储待办事项
|
||||
- 使用 DOM 操作动态更新列表
|
||||
- 为按钮添加事件监听器
|
||||
|
||||
### 练习2:实现一个数字猜谜游戏
|
||||
|
||||
计算机随机生成一个1到100之间的数字,玩家通过输入框猜测,程序提示"猜大了"或"猜小了",直到猜对为止。
|
||||
|
||||
提示:
|
||||
- 使用 `Math.random()` 生成随机数
|
||||
- 使用条件语句判断猜测结果
|
||||
- 记录并显示猜测次数
|
||||
|
||||
## 总结
|
||||
|
||||
JavaScript 是现代 web 开发的核心技术之一,它可以让网页变得动态和交互。通过学习变量、数据类型、运算符、条件语句、循环、函数和 DOM 操作等基础知识,你已经迈出了学习 JavaScript 的第一步。
|
||||
|
||||
继续练习和探索,你会发现 JavaScript 的强大功能和灵活性!
|
||||
Reference in New Issue
Block a user