HTML、JavaScript 与 TypeScript 基础速查
本文覆盖表单页面和前端小型逻辑最常用的 HTML、JavaScript 与 TypeScript 知识。
30 秒速查:遇到问题先看这里
在 CSDN 页面按 Ctrl+F 搜最后一列;要从头理解表单提交,读下一节完整例子。
| 现在遇到什么 | 先记住这一句 | 页内搜索 |
|---|---|---|
| 点击 label 没聚焦输入框? | HTML 的 label for 必须等于 input id。 |
## 3. 表单 |
| 点提交后页面刷新? | 监听 submit,在处理函数里调用 event.preventDefault()。 |
## 12. 表单事件 |
| 数组每项变成另一种值? | 用 map;它返回新数组。找一项用 find,筛选用 filter。 |
## 6. 对象与数组 |
find 的结果报 undefined? |
先处理"没找到"的分支,再访问属性。 | ## 13. 常见故障 |
| TS 不知道对象怎么写? | type Task = { id: number; title: string },列表是 Task[]。 |
## 10. 对象类型 |
| 函数参数/返回值报类型错? | 在函数边界写 id: number 和 : boolean 等类型。 |
## 10. 对象类型 |
| 导入失败? | 核对 export、import、相对路径 ./ 和文件名。 |
## 8. JavaScript 模块 |
先跟做:一个不用框架的任务表单
把下面内容保存为 task-demo.html,双击文件用浏览器打开。这个完整例子先用 HTML 画出输入框和列表,再用 JavaScript 处理"新增任务"。TypeScript 的类型写法在本文后半部分对照学习。
html
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>任务表单练习</title>
</head>
<body>
<h1>任务管理</h1>
<form id="task-form">
<!-- for 和 input 的 id 相同,点击"任务标题"也能聚焦输入框。 -->
<label for="task-title">任务标题</label>
<input id="task-title" name="title" type="text">
<button type="submit">新增</button>
</form>
<p id="message" role="alert"></p>
<ul id="task-list"></ul>
<script>
const form = document.querySelector("#task-form");
const input = document.querySelector("#task-title");
const message = document.querySelector("#message");
const list = document.querySelector("#task-list");
// 用户按 Enter 或点"新增"时,浏览器触发 submit 事件。
form.addEventListener("submit", function (event) {
event.preventDefault(); // 不让浏览器刷新页面。
const title = input.value.trim(); // 去掉前后空格。
if (title === "") {
message.textContent = "请输入任务标题";
return; // 输入无效,本次处理到这里结束。
}
const item = document.createElement("li");
item.textContent = title; // 用 textContent 显示文字,不当作 HTML 执行。
list.append(item); // 把新 li 放进 ul。
input.value = "";
message.textContent = "";
});
</script>
</body>
</html>
| 你做的操作 | 页面应该发生什么 |
|---|---|
| 输入"学习 Java"并点新增 | 列表出现"学习 Java",输入框清空 |
| 只输入空格并点新增 | 显示错误,列表不增加 |
| 刷新页面 | 列表清空,因为示例没有持久化保存 |
数据流可以读成:input.value 取得输入 → trim() 清理 → if 判断有效性 → createElement 创建元素 → append 更新页面。先能口述这条路径,再看下面的语法速查。
1. HTML 页面骨架
html
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>任务管理</title>
</head>
<body>
<main>
<h1>任务管理</h1>
<p>记录需要完成的事情。</p>
</main>
</body>
</html>
常见语义元素:
h1---h6:标题层级,不是调字号的工具。p:段落。ul/ol+li:无序/有序列表。main:页面主要内容。form:一组可以提交的表单控件。button:按钮。
2. 属性、嵌套与列表
html
<section aria-labelledby="task-heading">
<h2 id="task-heading">待办任务</h2>
<ul>
<li data-task-id="1">学习 Java</li>
<li data-task-id="2">练习 TypeScript</li>
</ul>
</section>
- 元素必须正确嵌套和闭合。
id在一个页面中应唯一。class可被多个元素复用。data-*保存与元素有关的自定义数据,但不要把敏感信息放入页面。
3. 表单、label、input 与 button
html
<form id="task-form">
<div>
<label for="task-title">任务标题</label>
<input
id="task-title"
name="title"
type="text"
required
maxlength="100"
>
</div>
<div>
<label for="completed">已完成</label>
<input id="completed" name="completed" type="checkbox">
</div>
<button type="submit">新增任务</button>
</form>
三个容易混淆的属性:
| 属性 | 主要职责 |
|---|---|
id |
页面内唯一标识,供 label、CSS、JS 使用 |
name |
表单提交时的字段名 |
type |
输入或按钮的行为类型 |
label for="task-title" 必须匹配 input id="task-title"。这样点击文字也能聚焦输入框,并改善无障碍体验。
浏览器校验可以改善体验,但服务器仍必须重新校验输入,因为客户端校验可以被绕过。
4. JavaScript 变量与基本判断
javascript
const maximum = 100; // 绑定不能重新赋值
let count = 0; // 可以重新赋值
function isValidTitle(title) {
const cleanTitle = title.trim();
if (cleanTitle === "") {
return false;
}
return true;
}
- 默认使用
const;确实需要重新赋值时使用let。 - 使用严格相等
===和严格不等!==。 const对象的属性仍可修改;它只禁止变量绑定到另一个对象。
5. 函数
javascript
function add(left, right) {
return left + right;
}
const multiply = (left, right) => left * right;
注意花括号箭头函数必须显式 return:
javascript
const names = tasks.map(task => {
return task.title;
});
6. 对象与数组
javascript
const task = {
id: 1,
title: "Java",
completed: false
};
console.log(task.title);
task.completed = true;
javascript
const tasks = [
{ id: 1, title: "Java", completed: false },
{ id: 2, title: "HTML", completed: true }
];
tasks.push({ id: 3, title: "TypeScript", completed: false });
for (const task of tasks) {
console.log(task.title);
}
常用数组方法:
javascript
const task = tasks.find(task => task.id === 2); // 对象或 undefined
const completed = tasks.filter(task => task.completed); // 新数组
const titles = tasks.map(task => task.title); // 新数组
const exists = tasks.some(task => task.id === 2); // boolean
map 的含义是"一项转换成一项",返回长度相同的新数组。不要用 map 只做打印或修改等副作用;这种情况通常更适合 for...of 或 forEach。
7. 一个完整的小型 JavaScript 例子
javascript
const tasks = [];
let nextId = 1;
function addTask(title) {
const cleanTitle = title.trim();
if (cleanTitle === "") return false;
tasks.push({
id: nextId,
title: cleanTitle,
completed: false
});
nextId += 1;
return true;
}
function toggleTask(id) {
const task = tasks.find(task => task.id === id);
if (task === undefined) return false;
task.completed = !task.completed;
return true;
}
function getTaskTitles() {
return tasks.map(task => task.title);
}
8. JavaScript 模块
javascript
// task.js
export function isValidTitle(title) {
return title.trim() !== "";
}
export const maximumTitleLength = 100;
javascript
// main.js
import { isValidTitle, maximumTitleLength } from "./task.js";
浏览器直接加载模块时:
html
<script type="module" src="./main.js"></script>
常见问题是遗漏相对路径的 ./、文件名大小写不一致、混淆命名导出与默认导出。
9. TypeScript 基本类型
typescript
const id: number = 1;
const title: string = "Java";
const completed: boolean = false;
const tags: string[] = ["backend", "training"];
TypeScript 能推断明显的局部类型,不必给每个变量都写类型:
typescript
const title = "Java"; // 推断为 string
优先明确函数边界和业务对象的类型。
10. 对象类型、数组类型与函数类型
typescript
type Task = {
id: number;
title: string;
completed: boolean;
};
const tasks: Task[] = [];
function findTask(id: number): Task | undefined {
return tasks.find(task => task.id === id);
}
function getTaskTitles(items: Task[]): string[] {
return items.map(task => task.title);
}
function toggleTask(id: number): boolean {
const task = findTask(id);
if (task === undefined) return false;
task.completed = !task.completed;
return true;
}
Task | undefined 表示调用者必须考虑"没有找到"这一分支。
11. type 与 interface
简单对象两者都可以:
typescript
type Task = {
id: number;
title: string;
};
interface TaskFormProps {
onSubmit: (title: string) => void;
}
初学阶段不用纠结统一答案,优先遵守当前仓库约定。type 也能表达联合类型;interface 常用于可扩展的对象契约。
12. 表单事件的最小连接
javascript
const form = document.querySelector("#task-form");
const titleInput = document.querySelector("#task-title");
form.addEventListener("submit", event => {
event.preventDefault();
const added = addTask(titleInput.value);
if (added) {
titleInput.value = "";
}
});
preventDefault() 阻止浏览器按传统表单方式刷新/跳转。真实项目中还要渲染结果并显示校验错误。
13. 常见故障速查
| 现象 | 首先检查 |
|---|---|
Cannot read properties of undefined |
find 是否没找到;是否检查 undefined |
map is not a function |
当前值是否真的是数组;API 响应结构是否与假设一致 |
| 点击 label 没聚焦 | for 和 id 是否完全一致 |
| 表单提交后页面刷新 | 是否监听 submit 并调用 preventDefault() |
| TypeScript 报可能为 undefined | 增加分支判断,不要盲目使用非空断言 ! |
| 修改数组后页面不更新 | 框架是否要求创建新数组/对象引用 |
| import 找不到模块 | 相对路径、扩展名、导出形式、文件名大小写 |
14. 快速自检
闭卷确认自己能写出:
- 正确关联 label 和 input 的表单。
- 一个对象数组与
find、filter、map。 - 一个命名导出与导入。
Task类型、Task[]、参数类型和返回类型。undefined分支和空白字符串校验。
官方参考资料
- MDN HTML:https://developer.mozilla.org/docs/Web/HTML
- MDN JavaScript:https://developer.mozilla.org/docs/Web/JavaScript
- JavaScript Modules:https://developer.mozilla.org/docs/Web/JavaScript/Guide/Modules
- TypeScript Everyday Types:https://www.typescriptlang.org/docs/handbook/2/everyday-types.html