【JS】JavaScript Web APIs DOM详解
·
一、事件基础
1.1 事件监听
事件监听是让程序检测是否有事件发生,一旦事件触发就立即调用函数响应。
基本语法:
元素.addEventListener('事件类型', 事件处理函数)
三要素:
- 事件源:哪个DOM元素
- 事件类型:什么事件(click、mouseenter等)
- 事件处理程序:事件触发时执行的函数
示例:
<button id="btn">点击我</button>
<script>
const btn = document.querySelector('#btn')
btn.addEventListener('click', function() {
console.log('按钮被点击了')
})
</script>
1.2 事件类型分类
鼠标事件
click- 鼠标点击dblclick- 鼠标双击mouseenter- 鼠标移入(无冒泡)mouseleave- 鼠标移出(无冒泡)mouseover- 鼠标移入(有冒泡)mouseout- 鼠标移出(有冒泡)
焦点事件
focus- 获得焦点blur- 失去焦点
键盘事件
keydown- 键盘按下keyup- 键盘抬起
表单事件
input- 输入框内容变化submit- 表单提交
1.3 事件对象
事件触发时会产生事件对象,包含事件相关信息。
常用事件对象属性:
| 属性 | 说明 | 适用事件 |
|---|---|---|
e.type | 事件类型 | 所有事件 |
e.target | 触发事件的元素 | 所有事件 |
e.clientX/Y | 光标相对窗口位置 | 鼠标事件 |
e.offsetX/Y | 光标相对元素位置 | 鼠标事件 |
e.key | 按键值 | 键盘事件 |
e.preventDefault() | 阻止默认行为 | 所有事件 |
e.stopPropagation() | 阻止事件传播 | 所有事件 |
获取事件对象:
元素.addEventListener('click', function(e) {
// e 就是事件对象
console.log(e.type) // 事件类型
console.log(e.clientX, e.clientY) // 光标相对窗口位置
console.log(e.offsetX, e.offsetY) // 光标相对元素位置
console.log(e.key) // 按键值(键盘事件)
})
二、事件进阶
2.1 事件流
事件流描述事件执行过程,包括两个阶段:
捕获阶段:从window → 目标元素(从父到子)
冒泡阶段:从目标元素 → window(从子到父)
控制执行阶段:
// 捕获阶段触发
element.addEventListener('click', handler, true)
// 冒泡阶段触发(默认)
element.addEventListener('click', handler, false)
2.2 阻止事件传播
element.addEventListener('click', function(e) {
e.stopPropagation() // 阻止事件冒泡/捕获
e.preventDefault() // 阻止默认行为
})
2.3 事件委托
利用事件冒泡,将子元素事件委托给父元素处理。
优势:
- 减少事件注册数量
- 动态添加的子元素也能触发事件
示例:
<ul id="list">
<li>选项1</li>
<li>选项2</li>
<li>选项3</li>
</ul>
<script>
document.getElementById('list').addEventListener('click', function(e) {
if(e.target.tagName === 'LI') {
console.log('点击了:', e.target.textContent)
}
})
</script>
三、特殊事件
3.1 页面加载事件
| 事件类型 | 触发时机 | 执行顺序 |
|---|---|---|
load | 所有资源加载完成 | 较晚 |
DOMContentLoaded | DOM加载完成 | 较早 |
// 等待页面所有资源加载完成
window.addEventListener('load', function() {
// 执行代码
})
// DOM加载完成即执行(不等待图片等资源)
document.addEventListener('DOMContentLoaded', function() {
// 执行代码
})
3.2 页面滚动事件
滚动相关属性:
| 属性 | 说明 | 读写性 |
|---|---|---|
scrollTop | 垂直滚动距离 | 可读写 |
scrollLeft | 水平滚动距离 | 可读写 |
scrollTo(x,y) | 滚动到指定位置 | 方法 |
window.addEventListener('scroll', function() {
// document.documentElement === html
// 获取滚动距离
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop
// 滚动到指定位置
window.scrollTo(0, 0)
// 或
document.documentElement.scrollTop = 0
})
3.3 页面尺寸事件
元素尺寸属性对比:
| 属性 | 包含内容 | 是否包含边框 | 是否包含滚动条 |
|---|---|---|---|
clientWidth/Height | content + padding | 否 | 否 |
offsetWidth/Height | content + padding + border | 是 | 是 |
scrollWidth/Height | 实际内容尺寸 | - | - |
window.addEventListener('resize', function() {
// 可视区域尺寸
const clientWidth = document.documentElement.clientWidth
const clientHeight = document.documentElement.clientHeight
// 元素尺寸(包含padding、border)
const element = document.querySelector('.box')
const offsetWidth = element.offsetWidth
const offsetHeight = element.offsetHeight
})
3.4 相关属性对比总结
| 属性 | 作用 | 说明 |
|---|---|---|
| scrollLeft和scrollTop | 被卷去的头部和左侧 | 配合页面滚动来用,可读写 |
| clientWidth和clientHeight | 获得元素宽度和高度 | 不包含border,margin,滚动条用于js获取元素大小,只读属性 |
| offsetWidth和offsetHeight | 获得元素宽度和高度 | 包含border、padding,滚动条等,只读 |
| offsetLeft和offsetTop | 获取元素距离自己定位父级元素的左、上距离 | 获取元素位置的时候使用,只读属性 |
四、DOM节点操作
4.1 节点关系查找
节点查找方法对比:
| 方法 | 返回内容 | 包含文本节点 |
|---|---|---|
parentNode | 父节点 | 是 |
children | 子元素节点 | 否 |
childNodes | 所有子节点 | 是 |
previousElementSibling | 上一个兄弟元素 | 否 |
nextElementSibling | 下一个兄弟元素 | 否 |
父子关系:
const parent = element.parentNode // 父节点
const children = element.children // 所有子元素节点
const childNodes = element.childNodes // 所有子节点(包含文本节点)
兄弟关系:
const prev = element.previousElementSibling // 上一个兄弟元素
const next = element.nextElementSibling // 下一个兄弟元素
4.2 节点创建与添加
节点操作方法:
| 方法 | 作用 | 参数说明 |
|---|---|---|
createElement() | 创建元素节点 | 标签名 |
appendChild() | 末尾添加节点 | 要添加的节点 |
insertBefore() | 指定位置添加 | (新节点, 参考节点) |
cloneNode() | 克隆节点 | true(深克隆)/false(浅克隆) |
removeChild() | 删除节点 | 要删除的节点 |
创建节点:
const newElement = document.createElement('div')
newElement.textContent = '新创建的元素'
newElement.className = 'new-class'
添加节点:
// 末尾添加
parent.appendChild(newElement)
// 指定位置添加
parent.insertBefore(newElement, referenceElement)
4.3 节点克隆与删除
克隆节点:
// 浅克隆(不包含子节点)
const clone = element.cloneNode(false)
// 深克隆(包含所有子节点)
const deepClone = element.cloneNode(true)
删除节点:
parent.removeChild(childElement)
五、日期对象
5.1 实例化日期
const now = new Date() // 当前时间
const specificDate = new Date('2024-01-01') // 指定时间
5.2 日期方法
| 方法 | 返回范围 | 说明 |
|---|---|---|
getFullYear() | 4位数年份 | 如:2024 |
getMonth() | 0-11 | 0表示1月 |
getDate() | 1-31 | 当月第几天 |
getDay() | 0-6 | 0表示周日 |
getHours() | 0-23 | 小时 |
getMinutes() | 0-59 | 分钟 |
getSeconds() | 0-59 | 秒数 |
const date = new Date()
date.getFullYear() // 四位年份
date.getMonth() // 月份 (0-11)
date.getDate() // 日期 (1-31)
date.getDay() // 星期 (0-6)
date.getHours() // 小时 (0-23)
date.getMinutes() // 分钟 (0-59)
date.getSeconds() // 秒数 (0-59)
console.log(date.getMonth() + 1) // 需要+1得到实际月份
// 本地化字符串
date.toLocaleString() // 完整日期时间
date.toLocaleDateString() // 仅日期
date.toLocaleTimeString() // 仅时间
5.3 时间戳
时间戳表示1970年1月1日至今的毫秒数。
获取时间戳:
const date = new Date()
const timestamp1 = date.getTime()
const timestamp2 = +new Date()
const timestamp3 = Date.now()
六、环境对象与回调函数
6.1 环境对象 (this)
this 指向函数运行时所在的环境。
this指向规则:
- 普通函数调用:
this→window - 对象方法调用:
this→ 调用该方法的对象 - 事件处理函数:
this→ 绑定事件的元素 - 构造函数调用:
this→ 新创建对象
function sayHi() {
console.log(this)
}
const user = {
name: '张三',
sayHi: sayHi
}
sayHi() // window
user.sayHi() // user对象
6.2 回调函数
将函数作为参数传递给另一个函数。
| 场景 | 示例 | 说明 |
|---|---|---|
| 定时器 | setInterval(callback, 1000) | 时间间隔执行 |
| 事件监听 | addEventListener('click', callback) | 事件触发执行 |
| 数组方法 | array.forEach(callback) | 遍历元素 |
| 异步操作 | fetch().then(callback) | 请求完成执行 |
// 回调函数示例
function mainFunction(callback) {
// 某些操作...
callback()
}
mainFunction(function() {
console.log('这是回调函数')
})
// 定时器中的回调
setInterval(function() {
console.log('定时器回调')
}, 1000)
七、事件监听方式对比
7.1 DOM L0 vs DOM L2
| 特性 | DOM L0 (on事件) | DOM L2 (addEventListener) |
|---|---|---|
| 事件覆盖 | 会覆盖 | 不会覆盖 |
| 执行阶段 | 仅冒泡 | 可控制捕获/冒泡 |
| 事件解绑 | onclick = null | removeEventListener |
| 匿名函数 | 支持解绑 | 不支持解绑匿名函数 |
| 推荐程度 | ★★☆☆☆ | ★★★★★ |
// DOM L0
btn.onclick = function() { alert('11') }
btn.onclick = function() { alert('22') } // 覆盖前一个
// DOM L2
btn.addEventListener('click', function() { alert('11') })
btn.addEventListener('click', function() { alert('22') }) // 两个都执行
八、实战案例
8.1 全选/反选功能
<table>
<tr>
<th><input type="checkbox" id="checkAll"> 全选</th>
<th>商品</th>
</tr>
<tr><td><input type="checkbox" class="item"></td><td>商品1</td></tr>
<tr><td><input type="checkbox" class="item"></td><td>商品2</td></tr>
</table>
<script>
const checkAll = document.getElementById('checkAll')
const items = document.querySelectorAll('.item')
// 全选控制单项
checkAll.addEventListener('click', function() {
items.forEach(item => {
item.checked = checkAll.checked
})
})
// 单项控制全选
items.forEach(item => {
item.addEventListener('click', function() {
checkAll.checked = document.querySelectorAll('.item:checked').length === items.length
})
})
</script>
8.2 回到顶部功能
const backToTop = document.createElement('div')
backToTop.textContent = '回到顶部'
backToTop.style.cssText = 'position:fixed;bottom:20px;right:20px;display:none;'
document.body.appendChild(backToTop)
window.addEventListener('scroll', function() {
const scrollTop = document.documentElement.scrollTop
backToTop.style.display = scrollTop > 300 ? 'block' : 'none'
})
backToTop.addEventListener('click', function() {
window.scrollTo({
top: 0,
behavior: 'smooth'
})
})
九、移动端触屏事件
9.1 触屏事件
| 事件类型 | 触发时机 | 说明 |
|---|---|---|
touchstart | 手指触摸屏幕 | 开始触摸 |
touchmove | 手指在屏幕滑动 | 触摸移动 |
touchend | 手指离开屏幕 | 触摸结束 |
element.addEventListener('touchstart', function(e) {
// 触摸开始
})
element.addEventListener('touchmove', function(e) {
// 触摸移动
})
element.addEventListener('touchend', function(e) {
// 触摸结束
})
9.2 Swiper插件
这份文档涵盖了Web APIs的核心概念,从基础的事件监听到高级的节点操作,提供了完整的知识体系和实用示例。
更多推荐


所有评论(0)