feat: add TypeScript lessons and learning panel

- Introduced a new script to check TypeScript lesson files for errors.
- Created a main TypeScript file to render lessons and their details.
- Added lesson definitions with starter and answer codes.
- Implemented a user interface for navigating and running lessons.
- Styled the application with CSS for a better user experience.
- Updated README to reflect the new TypeScript section and usage instructions.
This commit is contained in:
charlie
2026-03-19 10:06:11 +08:00
parent 69a4ae3178
commit f3bdaa4e88
146 changed files with 5951 additions and 9 deletions

View File

@@ -0,0 +1,26 @@
# 练习 8Promise 和渲染
## 目标
学会在 Promise 完成后把结果渲染到页面。
## 你要练什么
- Promise
- `.then()`
- `catch()`
- loading 状态
## 任务
- 点击按钮后显示“加载中”
- 等待 Promise 返回数据
- 把课程名称渲染到列表
- 如果失败,显示错误信息
## 文件
- [starter.html](/Users/lijiaqing/home/wwwroot/front-end-example/04-dom-events-async/08-promise-and-render/starter.html)
- [starter.js](/Users/lijiaqing/home/wwwroot/front-end-example/04-dom-events-async/08-promise-and-render/starter.js)
- [answer.html](/Users/lijiaqing/home/wwwroot/front-end-example/04-dom-events-async/08-promise-and-render/answer.html)
- [answer.js](/Users/lijiaqing/home/wwwroot/front-end-example/04-dom-events-async/08-promise-and-render/answer.js)

View File

@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Promise 和渲染</title>
<style>
body {
margin: 0;
padding: 32px;
font-family: "PingFang SC", "Microsoft YaHei", sans-serif;
background: #f4f7fb;
}
.panel {
max-width: 760px;
margin: 0 auto;
padding: 24px;
border-radius: 18px;
background: #ffffff;
border: 1px solid #dce3ef;
}
</style>
</head>
<body>
<section class="panel">
<h1>Promise 数据渲染</h1>
<button id="load-btn" type="button">加载课程</button>
<p id="status-text">等待加载</p>
<ul id="course-list"></ul>
</section>
<script src="./answer.js"></script>
</body>
</html>

View File

@@ -0,0 +1,30 @@
function fakeFetchCourses() {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(["DOM 获取元素", "事件监听", "异步基础"]);
}, 800);
});
}
const loadButton = document.getElementById("load-btn");
const statusText = document.getElementById("status-text");
const courseList = document.getElementById("course-list");
loadButton.addEventListener("click", function () {
statusText.textContent = "加载中...";
courseList.innerHTML = "";
fakeFetchCourses()
.then(function (courses) {
courses.forEach(function (course) {
const item = document.createElement("li");
item.textContent = course;
courseList.appendChild(item);
});
statusText.textContent = "加载完成";
})
.catch(function () {
statusText.textContent = "加载失败";
});
});

View File

@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Promise 和渲染</title>
<style>
body {
margin: 0;
padding: 32px;
font-family: "PingFang SC", "Microsoft YaHei", sans-serif;
background: #f4f7fb;
}
.panel {
max-width: 760px;
margin: 0 auto;
padding: 24px;
border-radius: 18px;
background: #ffffff;
border: 1px solid #dce3ef;
}
</style>
</head>
<body>
<section class="panel">
<h1>Promise 数据渲染</h1>
<button id="load-btn" type="button">加载课程</button>
<p id="status-text">等待加载</p>
<ul id="course-list"></ul>
</section>
<script src="./starter.js"></script>
</body>
</html>

View File

@@ -0,0 +1,14 @@
function fakeFetchCourses() {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(["DOM 获取元素", "事件监听", "异步基础"]);
}, 800);
});
}
// 任务:
// 1. 获取按钮、状态文字、列表
// 2. 点击按钮后显示“加载中”
// 3. 调用 fakeFetchCourses()
// 4. 用 then 渲染课程列表
// 5. 用 catch 处理错误