后端转全栈学习-Day6-JavaScript 基础-4

第6天:用 JS 操作网页(DOM 与事件)

学习时间:约 1.5 小时

前置知识:第5天的 JS 对象(知道对象是什么、怎么读写属性就够了)


目录

  1. 桥接:从第5天到第6天
  2. 环境准备:怎么跑今天代码
  3. [DOM 是什么](#DOM 是什么)
  4. 获取页面元素
  5. 操作页面元素
  6. 事件:让页面有反应
  7. 创建和删除元素
  8. 练习
  9. [选学:ES6 模块](#选学:ES6 模块)

1. 桥接:从第5天到第6天

1.1 先回忆一下第5天

第5天你在学 操作 JS 对象

js 复制代码
// 第5天:你在内存里操作对象
const user = { name: '小明', age: 25 }
user.name = '大明'           // 改属性
user.email = 'xm@test.com'   // 加属性
console.log(user.name)       // 读属性

这些对象存在 内存 里,你看不见它,只有 console.log 才能看到内容。

1.2 第6天要学什么

今天学的是 操作网页元素

js 复制代码
// 第6天:你要操作页面上的元素
const title = document.querySelector('h1')  // 找到 <h1> 标签
title.textContent = '新标题'                 // 改它显示的文本
title.style.color = 'red'                   // 改它的颜色

这些元素 显示在浏览器页面上,你改完马上就能看到效果。

1.3 一句话总结区别

第5天 第6天
操作内存里的 JS 对象 操作页面上的 HTML 标签
user.name = '大明' title.textContent = '新标题'
改完看不见,要 console.log 改完页面直接变化
纯 JS 语法 JS + 浏览器 API(DOM)

今天的核心就是:用 JS 找到页面上的标签,然后修改它。


2. 环境准备:怎么跑今天代码

2.1 你需要两个文件

今天的代码需要 一个 HTML 文件 + 一个 JS 文件

复制代码
day6-js-dom/
├── index.html       ← 页面结构
└── app.js           ← 你的 JS 代码

2.2 创建 index.html

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <title>第6天练习</title>
</head>
<body>
  <h1 id="title">欢迎</h1>
  <p class="text">这是一个段落。</p>
  <button id="btn">点击我</button>

  <!-- 重点:引入 JS 文件 -->
  <script src="app.js"></script>
</body>
</html>

关键行<script src="app.js"></script>------这个标签把 JS 文件连接到 HTML 页面。必须放在 </body> 前面(等所有标签加载完再执行 JS)。

2.3 创建 app.js

js 复制代码
// 随便写一行,验证连接成功
console.log('JS 文件已连接!')

2.4 运行方法

  1. 在 VS Code 里 :右键 index.html → "Open with Live Server"(最方便,自动刷新)
  2. 或者直接双击 index.html 文件(用浏览器打开)
  3. F12 打开控制台(Console),看 console.log 的输出

2.5 快速测试

app.js 改成下面的内容,刷新页面看效果:

js 复制代码
// 找到 <h1> 标签
const title = document.querySelector('#title')

// 修改它的文字
title.textContent = 'Hello DOM!'

// 改颜色
title.style.color = 'blue'

如果页面没反应 :检查 index.html 里有没有 <script src="app.js"></script>,文件名拼写对不对,控制台报不报错。


3. DOM 是什么

3.1 最简单的理解

打开浏览器 F12 → Elements 面板,你看到的 HTML 结构就是 DOM

DOM = 浏览器把 HTML 标签变成的一棵 JS 对象树。

比如这段 HTML:

html 复制代码
<div id="app">
  <h1>标题</h1>
  <p class="text">段落</p>
</div>

浏览器会把它变成一棵树:

复制代码
document(根对象)
  └── div#app
        ├── h1      → "标题"
        └── p.text  → "段落"

每个 HTML 标签(<div><h1><p>)在 JS 里都是一个 对象

3.2 用第5天的知识来理解

第5天的 JS 对象 第6天的 DOM 对象
你自己 {} 创建的 浏览器自动创建的
const user = { name: '小明' } <h1 id="title">标题</h1>
user.name 读属性 title.textContent 读文本
user.name = '大明' title.textContent = '新标题'

DOM 对象的本质就是对象 ------你在第5天学的增删改查,在 DOM 对象上一样能用,只是属性名不同(textContent 代替原来的 name)。

3.3 入口对象:document

js 复制代码
console.log(document)           // 整个页面的根对象
console.log(document.title)     // 页面标题(<title> 的内容)
console.log(document.body)      // <body> 标签

document 是浏览器给你的 全局对象 ,就像 console 一样,不用声明就能用。


4. 获取页面元素

在操作一个标签之前,先要 找到它。今天只学一个方法就够了:

4.1 querySelector --- CSS 选择器方式(推荐,一招吃遍天)

html 复制代码
<div id="app">
  <h1 class="title">标题</h1>
  <p class="text">第一段</p>
  <p class="text">第二段</p>
</div>
js 复制代码
// 通过 ID 获取(用 #)
const app = document.querySelector('#app')

// 通过 class 获取(用 .)
const title = document.querySelector('.title')

// 通过标签名获取
const h1 = document.querySelector('h1')

// 复杂选择器(和 CSS 一样)
const firstText = document.querySelector('#app > p.text')

特点 :参数是 CSS 选择器,返回 第一个匹配 的元素,找不到返回 null

4.2 querySelectorAll --- 获取所有匹配

js 复制代码
// 获取所有 class="text" 的元素
const allTexts = document.querySelectorAll('.text')

console.log(allTexts)            // NodeList [p.text, p.text]
console.log(allTexts.length)     // 2

// 遍历(和数组差不多)
allTexts.forEach(el => {
  console.log(el.textContent)
})

特点:返回所有匹配的元素(NodeList,类似数组),找不到返回空列表(不是 null)。

4.3 实战:验证你是否获取到了

js 复制代码
const app = document.querySelector('#app')

// 如果选择器写错了,返回 null
console.log(app)   // 写对了 → <div id="app">...</div>
                    // 写错了 → null

// 一定要判空!
if (app) {
  console.log('找到了 app 元素')
} else {
  console.log('没找到,检查选择器')
}

4.4 新手最容易犯的错

js 复制代码
// ❌ 在 DOM 还没加载完就获取元素
const btn = document.querySelector('#btn')   // null
btn.textContent = '按钮'                      // TypeError!

// ✅ 方案1:把 <script> 放在 </body> 前面(前面已讲)
// ✅ 方案2:等 DOM 加载完再执行
document.addEventListener('DOMContentLoaded', () => {
  const btn = document.querySelector('#btn')
  btn.textContent = '按钮'  // 现在 safe 了
})

5. 操作页面元素

找到元素后,怎么改它?下面是最常用的 5 种操作。

5.1 改文本:textContent

html 复制代码
<p id="msg">旧文本</p>
js 复制代码
const msg = document.querySelector('#msg')

// 读文本
console.log(msg.textContent)    // '旧文本'

// 改文本
msg.textContent = '新文本'
// 页面上立即变成"新文本"

5.2 改样式:style

html 复制代码
<div id="box">我是一个盒子</div>
js 复制代码
const box = document.querySelector('#box')

// 改行内样式(注意:CSS 属性名要转成驼峰)
box.style.color = 'red'
box.style.backgroundColor = '#f0f0f0'   // 原来是 background-color
box.style.fontSize = '20px'             // 原来是 font-size
box.style.padding = '20px'
box.style.borderRadius = '8px'

CSS 属性名 → JS 的转换规则

CSS JS
background-color style.backgroundColor
font-size style.fontSize
border-radius style.borderRadius
z-index style.zIndex

去掉横线,横线后的字母大写。

5.3 改 class:classList(推荐)

html 复制代码
<div id="box" class="box active">盒子</div>
js 复制代码
const box = document.querySelector('#box')

// 查看所有 class
console.log(box.className)              // 'box active'

// classList 更灵活(像 Set<String>)
box.classList.add('hidden')             // 添加 class
box.classList.remove('active')          // 删除 class
box.classList.toggle('visible')         // 有就删,没有就加(切换)

// 检查有没有某个 class
console.log(box.classList.contains('active'))  // false(刚删了)

实际场景 :用 toggle 实现开关效果

js 复制代码
// 每次点击按钮,切换 box 的 highlight 样式
const btn = document.querySelector('#btn')
const box = document.querySelector('#box')

btn.addEventListener('click', () => {
  box.classList.toggle('highlight')
})

配合 CSS:

css 复制代码
.highlight {
  background-color: yellow;
  box-shadow: 0 0 10px rgba(0,0,0,0.2);
}

5.4 改属性

html 复制代码
<input id="input" type="text" placeholder="请输入姓名" />
<img id="avatar" src="old.jpg" alt="头像" />
js 复制代码
const input = document.querySelector('#input')
const img = document.querySelector('#avatar')

// 直接读写属性
input.placeholder = '请输入新姓名'
input.value = '小明'              // 设置输入框的值
img.src = 'new.jpg'              // 换图片
img.alt = '新头像'

// 自定义属性用 dataset(HTML 写 data-xxx)
// <button data-id="123" data-type="primary">按钮</button>
const btn = document.querySelector('button')
console.log(btn.dataset.id)      // '123'
console.log(btn.dataset.type)    // 'primary'

5.5 操作速查

想做什么 代码
改文字 el.textContent = '新文字'
改样式 el.style.color = 'red'
加 class el.classList.add('active')
删 class el.classList.remove('active')
切换 class el.classList.toggle('active')
改属性 el.placeholder = '新提示'
读用户输入 input.value

6. 事件:让页面有反应

改样式、改文本都是你主动操作的。但如果想 用户点了按钮才执行代码,就需要事件。

6.1 什么是事件

事件 = 用户做了某个动作 → 你写的代码自动执行。

js 复制代码
// 翻译:当用户点击按钮时,执行这个函数
btn.addEventListener('click', () => {
  console.log('按钮被点了')
})

这个模式叫 事件监听------你在"等"用户做某个动作,用户做了,你的代码就跑起来。

6.2 三种最常见的事件

html 复制代码
<button id="btn">点我</button>
<input id="input" type="text" placeholder="输入..." />
<form id="form">
  <button type="submit">提交</button>
</form>
js 复制代码
// 1️⃣ 点击事件(最常用)
const btn = document.querySelector('#btn')
btn.addEventListener('click', () => {
  console.log('按钮被点击了')
  btn.textContent = '已点击'    // 改了按钮文字
  btn.style.background = 'green'
})

// 2️⃣ 输入事件(输入框内容变化时触发)
const input = document.querySelector('#input')
input.addEventListener('input', (e) => {
  // e.target 是触发事件的元素,这里就是 input
  console.log('当前输入:', e.target.value)
})

// 3️⃣ 表单提交事件
const form = document.querySelector('#form')
form.addEventListener('submit', (e) => {
  e.preventDefault()      // 阻止页面刷新(表单默认行为)
  console.log('提交了,但不刷新页面')
})

6.3 事件对象(e)

事件处理函数会自动收到一个 事件对象 (通常叫 eevent):

js 复制代码
btn.addEventListener('click', (e) => {
  console.log(e.type)          // 'click' --- 事件类型
  console.log(e.target)        // 你点的那个元素
  console.log(e.currentTarget) // 绑定监听的元素(大多数时候和 target 一样)

  e.preventDefault()           // 阻止默认行为(比如链接跳转、表单刷新)
  e.stopPropagation()          // 阻止事件冒泡(后面讲)
})

记住两个最常用的

方法/属性 作用 常用场景
e.target 用户点的到底是哪个元素 事件委托(后面讲)
e.preventDefault() 阻止浏览器的默认行为 表单提交时不刷新页面

6.4 完整例子:点击按钮改内容

html 复制代码
<div id="app">
  <p id="display">原始内容</p>
  <button id="changeBtn">点击修改</button>
</div>
js 复制代码
const display = document.querySelector('#display')
const changeBtn = document.querySelector('#changeBtn')

changeBtn.addEventListener('click', () => {
  display.textContent = '内容已被修改!'
  display.style.color = 'red'
})

效果:点按钮 → 段落文字变了 + 变红色。

6.5 addEventListener vs onclick

js 复制代码
// 方式 1:onclick(不推荐)
btn.onclick = () => console.log('第一次')
btn.onclick = () => console.log('第二次')  // ❌ 覆盖了第一次

// 方式 2:addEventListener(推荐)
btn.addEventListener('click', () => console.log('第一次'))
btn.addEventListener('click', () => console.log('第二次'))  // ✅ 两个都执行

永远用 addEventListener ,不要用 onclick/oninput 等 on 属性写法。


7. 创建和删除元素

7.1 创建新元素

js 复制代码
// 创建一个 <p> 标签(还没放到页面上)
const p = document.createElement('p')
p.textContent = '我是新创建的段落'
p.className = 'new-text'
p.style.color = 'blue'

createElement 只是创建了元素,还在内存里,没显示在页面上。

7.2 把元素放到页面上

html 复制代码
<ul id="list">
  <li>第一项</li>
</ul>
js 复制代码
const list = document.querySelector('#list')

// 创建新 li
const newLi = document.createElement('li')
newLi.textContent = '新添加的项'

// 追加到 ul 末尾(最常用)
list.appendChild(newLi)
// 页面多了:<li>新添加的项</li>

7.3 在指定位置插入

html 复制代码
<ul id="list">
  <li id="first">第一项</li>
  <li id="second">第二项</li>
</ul>
js 复制代码
const list = document.querySelector('#list')
const first = document.querySelector('#first')
const newLi = document.createElement('li')
newLi.textContent = '插入的项'

// 在 first 之前插入
list.insertBefore(newLi, first)

// 在 first 之后插入(更直观)
first.after(newLi)

// 在 first 之前插入
first.before(newLi)

7.4 删除元素

js 复制代码
// 方式 1:元素自己删除(推荐,更简洁)
const el = document.querySelector('.some-class')
el.remove()

// 方式 2:通过父元素删除
const parent = document.querySelector('#list')
const child = document.querySelector('#first')
parent.removeChild(child)

7.5 完整例子:动态添加列表项

html 复制代码
<div id="app">
  <input id="input" type="text" placeholder="输入内容" />
  <button id="addBtn">添加</button>
  <ul id="list"></ul>
</div>
js 复制代码
const input = document.querySelector('#input')
const addBtn = document.querySelector('#addBtn')
const list = document.querySelector('#list')

addBtn.addEventListener('click', () => {
  const text = input.value

  // 空输入不添加
  if (text === '') return

  // 创建 li
  const li = document.createElement('li')
  li.textContent = text

  // 添加到列表
  list.appendChild(li)

  // 清空输入框
  input.value = ''
})

这是今天第一个能跑起来的完整例子。自己敲一遍,看看效果。


8. 练习

练习 1:计数器

新建 counter.htmlcounter.js,用下面这个 HTML 结构:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <title>计数器</title>
</head>
<body>
  <div id="app">
    <button id="minus">-</button>
    <span id="count">0</span>
    <button id="plus">+</button>
  </div>
  <script src="counter.js"></script>
</body>
</html>

要求(JS 文件):

  1. 点击 + 按钮,数字加 1
  2. 点击 - 按钮,数字减 1
  3. 数字不能小于 0

提示

js 复制代码
const countEl = document.querySelector('#count')
// 读当前数字(textContent 是字符串,要转数字)
let count = Number(countEl.textContent)

练习 2:留言板

新建 message.htmlmessage.js

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <title>留言板</title>
</head>
<body>
  <div id="app">
    <input id="msgInput" type="text" placeholder="写留言..." />
    <button id="sendBtn">发送</button>
    <ul id="msgList"></ul>
  </div>
  <script src="message.js"></script>
</body>
</html>

要求

  1. 点击"发送"按钮,把输入内容添加到列表
  2. 输入为空时不能添加
  3. 点击列表项可以删除它(提示:el.remove()

练习 3:开关灯

在练习 1 或 2 的基础上加一个功能:切换深色/浅色模式

html 复制代码
<button id="themeToggle">切换深色模式</button>
js 复制代码
const toggle = document.querySelector('#themeToggle')

toggle.addEventListener('click', () => {
  // 在 body 上切换一个 class
  document.body.classList.toggle('dark-mode')
})

CSS(写在 HTML 的 <style> 里):

css 复制代码
.dark-mode {
  background-color: #333;
  color: white;
}
.dark-mode button {
  background-color: #555;
  color: white;
}

9. 选学:ES6 模块

这部分今天 可以跳过。DOM 操作不需要它,等开始用 Vue 时再回来学完全来得及。

9.1 模块解决什么问题

当一个 JS 文件太长时,你会想拆成多个文件:

js 复制代码
// 不拆分:一个文件几千行,找东西很难
// 拆分后:按功能拆成小文件,各管各的

模块就是 JS 的 文件拆分方案

9.2 导出和导入

js 复制代码
// ===== utils.js =====
export const PI = 3.14159

export function add(a, b) {
  return a + b
}

// ===== app.js =====
import { add, PI } from './utils.js'

console.log(add(1, 2))    // 3
console.log(PI)           // 3.14159

9.3 要在 HTML 里开启模块模式

html 复制代码
<script type="module" src="app.js"></script>

普通 script vs module script

普通 <script> <script type="module">
不支持 import 支持 import/export
变量在全局作用域 变量在模块作用域
按顺序加载 自动延迟加载

9.4 默认导出

js 复制代码
// ===== User.js =====
export default class User {
  constructor(name) {
    this.name = name
  }
}

// ===== app.js =====
import User from './User.js'
const user = new User('小明')

9.5 先别深究

你只需要知道:

  • JS 支持 import/export 来拆分文件
  • 用了模块的 script 要加 type="module"
  • 现在用不上,等学 Vue 时会大量用到

附:今日速查

js 复制代码
// === 获取元素 ===
document.querySelector('#id')       // 获取单个(用 CSS 选择器)
document.querySelectorAll('.cls')   // 获取所有匹配

// === 操作元素 ===
el.textContent = '新文本'           // 改文本
el.style.color = 'red'              // 改样式
el.classList.add('active')          // 添加 class
el.classList.remove('active')       // 删除 class
el.classList.toggle('active')       // 切换 class
el.value = '新值'                   // 改输入框内容

// === 创建和删除 ===
document.createElement('p')         // 创建元素
parent.appendChild(child)           // 追加到末尾
el.remove()                         // 删除自己

// === 事件 ===
el.addEventListener('click', fn)    // 添加点击事件
el.addEventListener('input', fn)    // 输入框内容变化
e.target                            // 用户点的元素
e.preventDefault()                  // 阻止默认行为
相关推荐
川冰ICE1 小时前
JavaScript实战②|电商网站交互效果,轮播图与购物车
开发语言·javascript·交互
数智工坊1 小时前
周志华《Machine Learning》学习笔记--第十四章--概率图模型
笔记·学习·机器学习
段一凡-华北理工大学1 小时前
工业领域的Hadoop架构学习~系列文章20:故障诊断与根因分析 - 从表象到本质的智能推理
大数据·人工智能·hadoop·学习·架构·高炉炼铁·工业智能体
凌云拓界1 小时前
状态机与思考循环 ——CogitoAgent开发实战(一)
javascript·人工智能·架构·node.js·设计规范
sugar__salt1 小时前
Bun 新一代 JavaScript/TypeScript 运行时:从入门到实战
开发语言·javascript·typescript
The moon forgets1 小时前
ABot-M0:基于动作流形学习的机器人操作VLA基础模型深度解析
人工智能·pytorch·python·学习·具身智能·vla·点云分割
05候补工程师2 小时前
【马原核心复习】唯物辩证法与认识论全景架构图解与精要笔记
经验分享·笔记·学习·考研
梦幻通灵2 小时前
Vue3 Element日期控件置灰明天之后日期
前端·javascript·vue.js
lzhdim2 小时前
C盘空间多出来4GB:谷歌服软 Chrome本地AI大模型可禁用、删除了
前端·人工智能·chrome