Appearance
DOM 与事件
JavaScript 基础篇介绍了变量、条件、循环、函数。但那些代码跑在 Console 里,跟页面没关系。JS 怎么改页面上的标题、怎么知道用户点了按钮、怎么读输入框里的值?这就需要 DOM。
DOM(Document Object Model)是浏览器把 HTML 解析后生成的页面对象树。JS 通过 DOM 读取元素、修改内容、监听事件——这就是"页面交互"的本质。
一、查找元素
document.querySelector 用 CSS 选择器找元素——跟 CSS 选择器写法一样,#title 按 id 找,.note 按 class 找:
html
<h1 id="page-title">文章管理</h1>
<p class="desc">第一段说明。</p>
<p class="desc">第二段说明。</p>js
const title = document.querySelector("#page-title"); // 找第一个匹配
const firstDesc = document.querySelector(".desc"); // 找第一个 class=desc
const allDescs = document.querySelectorAll(".desc"); // 找全部 class=desc
console.log(title.textContent); // 文章管理
console.log(allDescs.length); // 2querySelector 返回第一个匹配的元素(没找到返回 null),querySelectorAll 返回所有匹配的元素列表。JS 执行时 HTML 必须已经加载完——所以 <script> 放在 <body> 末尾,不然元素还没出来就去找,返回 null。
二、修改内容
改文字用 textContent,改 HTML 用 innerHTML:
js
const title = document.querySelector("#page-title");
title.textContent = "新标题"; // 纯文本
const box = document.querySelector("#box");
box.innerHTML = "<strong>加粗内容</strong>"; // 会解析成 HTML显示外部输入时优先用 textContent——innerHTML 会把字符串里的标签当成真实 HTML 执行,如果内容来自用户输入,可能被注入恶意代码。
改样式和 class:
js
const box = document.querySelector(".card");
box.classList.add("active"); // 加 class
box.classList.remove("hidden"); // 删 class
box.classList.toggle("selected"); // 有就删,没有就加classList 比直接拼 className 更安全——不会把原有的 class 覆盖掉。
改属性(比如链接地址、输入框值):
js
const link = document.querySelector("a");
link.href = "https://example.com";
const input = document.querySelector("input");
input.value = "预设值"; // 读输入框值也是 input.value三、创建元素
页面上的列表内容经常是动态的——从数据生成。document.createElement 创建新元素,appendChild 挂到父元素上:
html
<ul id="article-list"></ul>js
const list = document.querySelector("#article-list");
const articles = ["Python 入门", "Go 并发", "Rust 安全"];
// 先清空旧内容
list.innerHTML = "";
// 逐条创建列表项
for (const title of articles) {
const item = document.createElement("li");
item.textContent = title;
list.appendChild(item);
}list.innerHTML = "" 清空旧内容——重新渲染列表前的标准操作。
四、事件
事件表示页面上发生了动作——点击、输入、提交。addEventListener 监听事件:
html
<button id="btn" type="button">点击</button>
<p id="msg"></p>js
const button = document.querySelector("#btn");
const msg = document.querySelector("#msg");
button.addEventListener("click", () => {
msg.textContent = "按钮被点了";
});addEventListener("click", 回调函数)——用户点击时,浏览器调回调函数。常见事件:click(点击元素)、input(输入框内容变化,每打一个字触发)、change(输入框失焦或选择变化时触发)、submit(表单提交)、keydown(键盘按下)。
实时预览输入内容:
html
<input id="title-input" type="text">
<p id="preview"></p>js
const input = document.querySelector("#title-input");
const preview = document.querySelector("#preview");
input.addEventListener("input", () => {
preview.textContent = input.value; // 每打一个字就更新预览
});input.value 读输入框当前值。input 事件每打一个字触发一次——搜索框实时筛选、表单实时校验都用它。
五、表单处理
表单默认提交会刷新页面(浏览器按 action 跳转)。用 JS 处理表单时,先阻止默认提交,再读取字段:
html
<form id="article-form">
<label for="title">标题</label>
<input id="title" name="title" type="text" required>
<label for="category">分类</label>
<select id="category" name="category">
<option value="tech">技术</option>
<option value="life">生活</option>
</select>
<button type="submit">提交</button>
</form>
<pre id="result"></pre>js
const form = document.querySelector("#article-form");
const result = document.querySelector("#result");
form.addEventListener("submit", (event) => {
event.preventDefault(); // 阻止页面刷新
// FormData 按 name 收集所有字段值
const formData = new FormData(form);
const data = Object.fromEntries(formData.entries());
result.textContent = JSON.stringify(data, null, 2);
});event.preventDefault() 是关键——不写的话表单提交后页面直接刷新,JS 代码来不及执行。FormData 按字段的 name 属性收集值,输入框缺 name 时数据里不会有这个字段。
六、完整示例:文章列表
把 DOM 操作和事件合到一个页面:从内存数据渲染文章列表,表单新增文章后实时更新页面。这个例子不调后端 API——数据只存在浏览器内存里,刷新会丢。调 API 是下一篇(异步与网络请求)的事。
文件:index.html
html
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>文章管理</title>
</head>
<body>
<h1>文章管理</h1>
<ul id="article-list"></ul>
<form id="article-form">
<label for="title">标题</label>
<input id="title" name="title" type="text" required>
<label for="category">分类</label>
<select id="category" name="category">
<option value="tech">技术</option>
<option value="life">生活</option>
</select>
<button type="submit">新增</button>
</form>
<script src="app.js"></script>
</body>
</html>文件:app.js
js
// 初始数据(存在内存里,刷新会丢)
let articles = [
{ title: "Python 入门", category: "tech" },
{ title: "读书笔记", category: "life" },
];
const list = document.querySelector("#article-list");
const form = document.querySelector("#article-form");
// 渲染列表
function renderArticles() {
list.innerHTML = ""; // 先清空
for (const article of articles) {
const item = document.createElement("li");
item.textContent = `${article.title}(${article.category})`;
list.appendChild(item);
}
}
// 表单提交:新增文章
form.addEventListener("submit", (event) => {
event.preventDefault();
const formData = new FormData(form);
const data = Object.fromEntries(formData.entries());
articles.push(data); // 加到数组末尾
form.reset(); // 清空表单
renderArticles(); // 重新渲染
});
// 页面加载后先渲染一次
renderArticles();打开页面看到两篇文章。在表单里填一篇新的,点新增——列表立刻多了一条。整个过程不刷新页面、不调后端,纯靠 DOM 操作。这就是"前端交互"的基本形态。
七、常见问题
| 现象 | 常见原因 | 排查入口 |
|---|---|---|
| 元素读不到(返回 null) | JS 执行时 HTML 还没加载,或选择器写错 | <script> 放 body 末尾、Console 查选择器 |
| 表单提交后页面刷新 | 没调 event.preventDefault() | submit 事件处理 |
| 字段没进 FormData | 输入框缺 name 属性 | 表单 HTML |
| 点击没反应 | 事件名写错(onClick vs click)或元素没找到 | Console 看有没有报错 |
DOM 问题看 Elements 和 Console,请求问题看 Network——F12 打开开发者工具,这三个面板覆盖了前端排查 90% 的场景。