feat: 添加前端项目基础配置和阶段示例
添加 .editorconfig 配置文件用于统一编辑器设置,包括缩进风格、 换行符、字符集等规范。 添加 jsconfig.json 配置文件用于 JavaScript 项目的编译选项, 启用类型检查和模块解析配置。 添加 stage00 到 stage03 四个阶段的 HTML 和 JavaScript 示例: - stage00: 基础 HTML 结构演示 - stage01: 纯命令式 DOM 操作实现用户卡片 - stage02: 声明式渲染方式重构用户卡片生成 - stage03: 扩展支持列表渲染多个用户数据 每个阶段都包含对应的 HTML 入口文件和 JavaScript 实现逻辑, 逐步展示从命令式到声明式渲染的演进过程。
This commit is contained in:
12
.editorconfig
Normal file
12
.editorconfig
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# EditorConfig is awesome: https://EditorConfig.org
|
||||||
|
|
||||||
|
# top-most EditorConfig file
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
end_of_line = crlf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
insert_final_newline = false
|
||||||
17
jsconfig.json
Normal file
17
jsconfig.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"checkJs": true,
|
||||||
|
"strict": false,
|
||||||
|
"target": "ES2020",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"moduleDetection": "force",
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"*.js",
|
||||||
|
"stage*/**/*.js"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules"
|
||||||
|
]
|
||||||
|
}
|
||||||
15
stage00/index.html
Normal file
15
stage00/index.html
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='zh-cn'>
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8'>
|
||||||
|
<meta name='viewport' content='width=device-width, initial-scale=1'>
|
||||||
|
<title>Stage 00 using html</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="minivue">
|
||||||
|
<h2>姓名: 小明</h2>
|
||||||
|
<span>年龄: 18</span>
|
||||||
|
<p>学生</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
12
stage01/index.html
Normal file
12
stage01/index.html
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Stage 01 - 命令式 DOM</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="minivue"></div>
|
||||||
|
<script src="./index.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
24
stage01/index.js
Normal file
24
stage01/index.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* Stage 01:纯命令式 DOM 操作
|
||||||
|
* 每一步都直接创建、组装、插入节点
|
||||||
|
*/
|
||||||
|
|
||||||
|
const card = document.createElement("div");
|
||||||
|
card.className = "user-card";
|
||||||
|
|
||||||
|
const nameEl = document.createElement("h2");
|
||||||
|
nameEl.textContent = "姓名: 小明";
|
||||||
|
|
||||||
|
const ageEl = document.createElement("p");
|
||||||
|
ageEl.textContent = "年龄: 18";
|
||||||
|
|
||||||
|
const tagEl = document.createElement("span");
|
||||||
|
tagEl.textContent = "学生";
|
||||||
|
|
||||||
|
card.appendChild(nameEl);
|
||||||
|
card.appendChild(ageEl);
|
||||||
|
card.appendChild(tagEl);
|
||||||
|
|
||||||
|
const root = document.getElementById("minivue");
|
||||||
|
console.assert(root != null, "容器 #minivue 未找到");
|
||||||
|
root.appendChild(card);
|
||||||
12
stage02/index.html
Normal file
12
stage02/index.html
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='zh-cn'>
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8'>
|
||||||
|
<meta name='viewport' content='width=device-width, initial-scale=1'>
|
||||||
|
<title>Stage 02: 声明式渲染</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="minivue"></div>
|
||||||
|
<script src="./index.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
42
stage02/index.js
Normal file
42
stage02/index.js
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* Stage 02:声明式渲染
|
||||||
|
* 把“数据 → DOM”封装为函数,数据变了只需重新调用函数
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据用户数据生成卡片 DOM 节点
|
||||||
|
* @param {{ name: string, age: number, tag: string }} user
|
||||||
|
* @returns {HTMLDivElement}
|
||||||
|
*/
|
||||||
|
function generateUser(user) {
|
||||||
|
const card = document.createElement("div");
|
||||||
|
card.className = "user-card";
|
||||||
|
|
||||||
|
const name = document.createElement("h2");
|
||||||
|
name.textContent = "姓名: " + user.name;
|
||||||
|
|
||||||
|
const age = document.createElement("p");
|
||||||
|
age.textContent = "年龄: " + user.age;
|
||||||
|
|
||||||
|
const tag = document.createElement("span");
|
||||||
|
tag.textContent = user.tag;
|
||||||
|
|
||||||
|
card.appendChild(name);
|
||||||
|
card.appendChild(age);
|
||||||
|
card.appendChild(tag);
|
||||||
|
return card;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将用户卡片挂载到指定容器
|
||||||
|
* @param {{ name: string, age: number, tag: string }} user
|
||||||
|
* @param {HTMLElement} container
|
||||||
|
*/
|
||||||
|
function renderUser(user, container) {
|
||||||
|
container.appendChild(generateUser(user));
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = { name: "小明", age: 18, tag: "学生" };
|
||||||
|
|
||||||
|
const root = document.getElementById("minivue");
|
||||||
|
renderUser(user, root);
|
||||||
12
stage03/index.html
Normal file
12
stage03/index.html
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='zh-cn'>
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8'>
|
||||||
|
<meta name='viewport' content='width=device-width, initial-scale=1'>
|
||||||
|
<title>Stage 03: 列表渲染</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="minivue"></div>
|
||||||
|
<script src="./index.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
50
stage03/index.js
Normal file
50
stage03/index.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
* Stage 03:列表渲染
|
||||||
|
* 用循环对数组中的每个数据项调用渲染函数
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据用户数据生成卡片 DOM 节点
|
||||||
|
* @param {{ name: string, age: number, tag: string }} user
|
||||||
|
* @returns {HTMLDivElement}
|
||||||
|
*/
|
||||||
|
function generateUser(user) {
|
||||||
|
const card = document.createElement("div");
|
||||||
|
card.className = "user-card";
|
||||||
|
|
||||||
|
const name = document.createElement("h2");
|
||||||
|
name.textContent = "姓名: " + user.name;
|
||||||
|
|
||||||
|
const age = document.createElement("p");
|
||||||
|
age.textContent = "年龄: " + user.age;
|
||||||
|
|
||||||
|
const tag = document.createElement("span");
|
||||||
|
tag.textContent = user.tag;
|
||||||
|
|
||||||
|
card.appendChild(name);
|
||||||
|
card.appendChild(age);
|
||||||
|
card.appendChild(tag);
|
||||||
|
return card;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将用户卡片挂载到指定容器
|
||||||
|
* @param {{ name: string, age: number, tag: string }} user
|
||||||
|
* @param {HTMLElement} container
|
||||||
|
*/
|
||||||
|
function renderUser(user, container) {
|
||||||
|
container.appendChild(generateUser(user));
|
||||||
|
}
|
||||||
|
|
||||||
|
const multiUser = [
|
||||||
|
{ name: "小明", age: 18, tag: "学生" },
|
||||||
|
{ name: "小王", age: 19, tag: "学生" },
|
||||||
|
{ name: "小李", age: 20, tag: "学生" },
|
||||||
|
{ name: "小孙", age: 56, tag: "校长" },
|
||||||
|
{ name: "小赵", age: 43, tag: "老师" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const root = document.getElementById("minivue");
|
||||||
|
for (let i = 0; i < multiUser.length; i++) {
|
||||||
|
renderUser(multiUser[i], root);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user