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:
25
04-dom-events-async/11-input-live-preview/README.md
Normal file
25
04-dom-events-async/11-input-live-preview/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# 练习 11:input 实时预览
|
||||
|
||||
## 目标
|
||||
|
||||
学会处理输入类事件,让页面随着用户输入实时变化。
|
||||
|
||||
## 你要练什么
|
||||
|
||||
- `input` 事件
|
||||
- `change` 事件
|
||||
- 表单值读取
|
||||
- 实时 DOM 更新
|
||||
|
||||
## 任务
|
||||
|
||||
- 在输入框输入昵称时,实时更新预览标题
|
||||
- 在文本域输入学习目标时,实时更新预览内容
|
||||
- 切换学习阶段下拉框时,更新阶段标签
|
||||
|
||||
## 文件
|
||||
|
||||
- [starter.html](/Users/lijiaqing/home/wwwroot/front-end-example/04-dom-events-async/11-input-live-preview/starter.html)
|
||||
- [starter.js](/Users/lijiaqing/home/wwwroot/front-end-example/04-dom-events-async/11-input-live-preview/starter.js)
|
||||
- [answer.html](/Users/lijiaqing/home/wwwroot/front-end-example/04-dom-events-async/11-input-live-preview/answer.html)
|
||||
- [answer.js](/Users/lijiaqing/home/wwwroot/front-end-example/04-dom-events-async/11-input-live-preview/answer.js)
|
||||
86
04-dom-events-async/11-input-live-preview/answer.html
Normal file
86
04-dom-events-async/11-input-live-preview/answer.html
Normal file
@@ -0,0 +1,86 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>input 实时预览</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 32px;
|
||||
font-family: "PingFang SC", "Microsoft YaHei", sans-serif;
|
||||
background: #f6f8fb;
|
||||
}
|
||||
|
||||
.page {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 18px;
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.panel {
|
||||
padding: 24px;
|
||||
border-radius: 18px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #dce4ef;
|
||||
}
|
||||
|
||||
label {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
input,
|
||||
textarea,
|
||||
select {
|
||||
padding: 10px 12px;
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 6px 12px;
|
||||
border-radius: 999px;
|
||||
background: #dbeafe;
|
||||
color: #1d4ed8;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main class="page">
|
||||
<section class="panel">
|
||||
<h1>编辑资料</h1>
|
||||
|
||||
<label for="nickname-input">
|
||||
昵称
|
||||
<input id="nickname-input" type="text" placeholder="输入你的昵称" />
|
||||
</label>
|
||||
|
||||
<label for="goal-input">
|
||||
学习目标
|
||||
<textarea id="goal-input" rows="4" placeholder="输入今天的学习目标"></textarea>
|
||||
</label>
|
||||
|
||||
<label for="stage-select">
|
||||
学习阶段
|
||||
<select id="stage-select">
|
||||
<option value="入门阶段">入门阶段</option>
|
||||
<option value="DOM 阶段">DOM 阶段</option>
|
||||
<option value="异步阶段">异步阶段</option>
|
||||
</select>
|
||||
</label>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<p class="badge" id="preview-stage">入门阶段</p>
|
||||
<h2 id="preview-name">未填写昵称</h2>
|
||||
<p id="preview-goal">这里会显示你的学习目标。</p>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<script src="./answer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
21
04-dom-events-async/11-input-live-preview/answer.js
Normal file
21
04-dom-events-async/11-input-live-preview/answer.js
Normal file
@@ -0,0 +1,21 @@
|
||||
const nicknameInput = document.getElementById("nickname-input");
|
||||
const goalInput = document.getElementById("goal-input");
|
||||
const stageSelect = document.getElementById("stage-select");
|
||||
|
||||
const previewStage = document.getElementById("preview-stage");
|
||||
const previewName = document.getElementById("preview-name");
|
||||
const previewGoal = document.getElementById("preview-goal");
|
||||
|
||||
nicknameInput.addEventListener("input", function () {
|
||||
const value = nicknameInput.value.trim();
|
||||
previewName.textContent = value || "未填写昵称";
|
||||
});
|
||||
|
||||
goalInput.addEventListener("input", function () {
|
||||
const value = goalInput.value.trim();
|
||||
previewGoal.textContent = value || "这里会显示你的学习目标。";
|
||||
});
|
||||
|
||||
stageSelect.addEventListener("change", function () {
|
||||
previewStage.textContent = stageSelect.value;
|
||||
});
|
||||
86
04-dom-events-async/11-input-live-preview/starter.html
Normal file
86
04-dom-events-async/11-input-live-preview/starter.html
Normal file
@@ -0,0 +1,86 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>input 实时预览</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 32px;
|
||||
font-family: "PingFang SC", "Microsoft YaHei", sans-serif;
|
||||
background: #f6f8fb;
|
||||
}
|
||||
|
||||
.page {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 18px;
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.panel {
|
||||
padding: 24px;
|
||||
border-radius: 18px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #dce4ef;
|
||||
}
|
||||
|
||||
label {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
input,
|
||||
textarea,
|
||||
select {
|
||||
padding: 10px 12px;
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 6px 12px;
|
||||
border-radius: 999px;
|
||||
background: #dbeafe;
|
||||
color: #1d4ed8;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main class="page">
|
||||
<section class="panel">
|
||||
<h1>编辑资料</h1>
|
||||
|
||||
<label for="nickname-input">
|
||||
昵称
|
||||
<input id="nickname-input" type="text" placeholder="输入你的昵称" />
|
||||
</label>
|
||||
|
||||
<label for="goal-input">
|
||||
学习目标
|
||||
<textarea id="goal-input" rows="4" placeholder="输入今天的学习目标"></textarea>
|
||||
</label>
|
||||
|
||||
<label for="stage-select">
|
||||
学习阶段
|
||||
<select id="stage-select">
|
||||
<option value="入门阶段">入门阶段</option>
|
||||
<option value="DOM 阶段">DOM 阶段</option>
|
||||
<option value="异步阶段">异步阶段</option>
|
||||
</select>
|
||||
</label>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<p class="badge" id="preview-stage">入门阶段</p>
|
||||
<h2 id="preview-name">未填写昵称</h2>
|
||||
<p id="preview-goal">这里会显示你的学习目标。</p>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<script src="./starter.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
6
04-dom-events-async/11-input-live-preview/starter.js
Normal file
6
04-dom-events-async/11-input-live-preview/starter.js
Normal file
@@ -0,0 +1,6 @@
|
||||
// 任务:
|
||||
// 1. 获取昵称输入框、目标文本域、阶段下拉框
|
||||
// 2. 监听昵称和目标的 input 事件
|
||||
// 3. 把输入内容实时渲染到右侧预览
|
||||
// 4. 监听阶段下拉框的 change 事件
|
||||
// 5. 更新阶段标签文字
|
||||
Reference in New Issue
Block a user