前端入门学习笔记(Day09):JavaScript DOM 全流程操作实战(查找 / 修改 / 事件 / 窗口交互)

引入:

在前八天的学习中,我们已掌握 HTML 结构搭建、CSS 样式美化,以及 JavaScript 的变量、函数、流程控制等基础能力(Day01-Day08),但前端开发的核心价值在于 “动态交互”—— 比如用户点击按钮修改内容、提交表单验证数据、缩放窗口实时响应,这些都需要通过操作 DOM(文档对象模型)实现。​

DOM 是 HTML 文档的编程接口,将页面元素转化为可被 JavaScript 操作的对象。Day09覆盖 DOM 操作全流程:从 “查找元素”(获取要操作的目标),到 “修改内容与样式”(改变元素呈现),再到 “绑定事件”(响应用户操作),最后到 “窗口与表单交互”(适配页面环境与用户输入)。

一、DOM 元素查找:精准定位页面元素的 4 种核心方法

DOM(文档对象模型)将 HTML 页面解析为树状结构,要操作页面元素,首先需通过 DOM API “找到” 目标元素。Day09 第一个代码文件演示了 4 种常用的元素查找方式,适用于不同场景,是 DOM 操作的基础前提。

1.1 通过 ID 查找(getElementById):唯一元素的快速定位

  • 核心特点:id是 HTML 元素的唯一标识(一个页面中不能有重复id),因此getElementById返回单个元素对象,查找效率最高,是开发中定位唯一元素(如页面容器、表单提交按钮)的首选方式。
  • 语法:document.getElementById("元素id值")
  • 代码解析
  • // 查找id为"context"的div元素(页面中唯一)
    
    var context = document.getElementById("context");
    
    console.log(context); // 输出:<div id="context">...</div>(整个div元素对象)

  • 使用场景:定位页面中唯一存在的元素,如顶部导航栏、页脚容器、弹窗主体等,结合 Day05 中 “修改元素样式” 的知识点,可快速实现单个元素的动态操作。

1.2 通过类名查找(getElementsByClassName):同类元素的批量获取

  • 核心特点:class用于为多个元素定义相同样式或逻辑,因此getElementsByClassName返回HTMLCollection(类数组对象),包含所有指定类名的元素,需通过索引(如[0])或循环遍历单个元素。
  • 语法:document.getElementsByClassName("元素class值")
  • 代码解析
// 查找所有class为"text"的p元素(页面中有2个:第一段、第二段文字)

var text = document.getElementsByClassName("text");

console.log(text); // 输出:HTMLCollection(2) [p.text, p.text](类数组对象)

console.log(text[0]); // 输出:<p class="text">第一段文字</p>(第一个class为"text"的元素)
  • 注意事项:方法名中 “Elements” 为复数形式(不可省略 “s”),否则会报错;返回的类数组对象不支持 forEach 循环,需用 for 循环遍历(如for(var i=0;i<text.length;i++){...})。
  • 使用场景:批量操作同类元素,如商品列表中的所有商品卡片、表单中的所有输入框,结合 Day07 数组遍历的思路,可实现同类元素的统一样式修改或逻辑处理。

1.3 通过标签名查找(getElementsByTagName):同类型元素的全局获取

  • 核心特点:根据 HTML 标签名(如p、div、ul)查找元素,返回HTMLCollection(类数组对象),包含页面中所有该类型的元素,适用范围最广,但查找精度较低。
  • 语法:document.getElementsByTagName("HTML标签名")
  • 代码解析
// 查找页面中所有p标签元素(共3个:class为text的2个 + class为ptext的1个)

var ptext = document.getElementsByTagName("p");

console.log(ptext); // 输出:HTMLCollection(3) [p.text, p.text, p.ptext]
  • 使用场景:获取页面中某一类型的所有元素,如统计页面中图片数量(getElementsByTagName("img"))、清空所有输入框内容(getElementsByTagName("input")),常与 “批量操作” 需求结合。

1.4 通过 CSS 选择器查找(querySelectorAll):灵活精准的多条件匹配

  • 核心特点:支持 CSS 选择器语法(如类选择器.、ID 选择器#、后代选择器ul li、伪类选择器:first-child),返回NodeList(类数组对象),可满足复杂的元素查找需求,灵活性最高。
  • 语法:document.querySelectorAll("CSS选择器")
  • 代码解析
// 1. 查找ul下的所有li元素(后代选择器)

var allList = document.querySelectorAll("ul li");

console.log(allList); // 输出:NodeList(3) [li, li, li](3个列表项)

// 2. 查找ul下的第一个li元素(伪类选择器:first-child)

var firstList = document.querySelectorAll("ul li:first-child");

console.log(firstList); // 输出:NodeList(1) [li](仅第一个列表项)

// 3. 查找ul下的第二个li元素(伪类选择器:nth-child(1),注意:nth-child从1开始计数)

var secondList = document.querySelectorAll("ul li:nth-child(1)");

console.log(secondList); // 输出:NodeList(1) [li](第二个列表项)
  • 优势与注意
  • 相比前三种方法,支持更复杂的选择逻辑(如"div.text > p"选择 class 为 text 的 div 下的直接子 p 元素);
  • 返回的 NodeList 对象支持 forEach 循环(如allList.forEach(item => console.log(item))),遍历更便捷;
  • 若只需查找单个元素,可使用querySelector(无 “All”),返回匹配的第一个元素(如document.querySelector("ul li:first-child"))。
  • 使用场景:复杂条件下的元素查找,如 “查找第三个商品卡片中的加入购物车按钮”“定位表单中带有必填标记的输入框”,是开发中灵活性最高的查找方式。

1.5 四种查找方式的对比与选择建议

查找方法

返回结果类型

查找依据

适用场景

优势

getElementById

单个元素对象

元素 id

定位唯一元素(如容器、按钮)

效率最高,唯一匹配

getElementsByClassName

HTMLCollection

元素 class

批量操作同类元素

按功能分组查找,灵活

getElementsByTagName

HTMLCollection

HTML 标签名

全局获取同类型元素

范围广,无需提前定义 class

querySelectorAll

NodeList

CSS 选择器

复杂条件查找

支持多语法,灵活性最高

二、DOM 元素内容修改

找到目标元素后,最常见的需求是修改元素内容(如动态更新文本、插入 HTML 结构)。Day09 第二个代码文件对比了textContent与innerHTML两种修改方式,二者核心差异在于是否解析 HTML 标签,需根据场景选择。

2.1 textContent:纯文本内容修改(安全无风险)

  • 核心特点:仅修改元素的纯文本内容,不解析 HTML 标签,所有传入的内容都会被当作普通文本显示,避免 XSS(跨站脚本攻击)风险,是纯文本更新的首选方式。
  • 语法:元素.textContent = "新的纯文本内容"
  • 代码解析
function changeContext() {

var context = document.getElementById("context");

// 修改为纯文本“这是新的文本信息”,无HTML解析

context.textContent = "这是新的文本信息";

// 页面显示:这是新的文本信息(无格式,纯文字)

}
  • 使用场景:动态更新普通文本内容,如商品价格变动、倒计时数字更新、用户昵称显示等,确保内容仅为文字,无 HTML 结构时使用。

2.2 innerHTML:HTML 结构内容修改(支持标签解析)

  • 核心特点:可传入包含 HTML 标签的字符串,会解析标签并渲染为 DOM 结构,能实现文本格式美化(如加粗、换行)或插入复杂 HTML 元素,但存在 XSS 风险(若内容来自用户输入,可能注入恶意脚本)。
  • 语法:元素.innerHTML = "包含HTML标签的内容"
  • 代码解析(结合定时器)
function changeContext() {

var context = document.getElementById("context");

// 2秒后(setTimeout延迟执行),插入带<strong>标签的内容

setTimeout(() => {

context.innerHTML = "<strong>这是你好</strong>";

// 页面显示:这是你好(文字加粗,因<strong>标签被解析)

}, 2000); // 2000ms=2秒,Day07定时器知识点的实际应用

}
  • 优势与风险
  • 优势:支持插入复杂 HTML 结构(如<div><p>新内容</p></div>),可快速动态生成页面元素(如商品列表项);
  • 风险:若内容包含用户输入(如评论、留言),需先过滤 HTML 标签,否则可能被注入恶意代码(如<script>恶意代码</script>)。
  • 使用场景:需要动态插入带格式的文本(如加粗标题、换行说明)或复杂 HTML 结构(如动态生成的表单、弹窗内容)时使用,结合 Day05 “DOM 交互” 知识点,实现页面内容的动态更新。

2.3 textContent 与 innerHTML 的核心差异对比

修改方式

是否解析 HTML 标签

安全性

适用场景

示例结果

textContent

高(无 XSS)

纯文本更新(价格、数字)

输入<strong>文本</strong>,显示<strong>文本</strong>

innerHTML

低(需过滤)

带格式文本或 HTML 结构插入

输入<strong>文本</strong>,显示文本(加粗)

2.4 用 JavaScript 动态修改 DOM 元素样式:操作 style 属性

在前端开发中,通过 JS 动态修改元素样式是实现 “交互反馈” 的核心手段(如按钮点击后变色、表单验证失败时标红输入框)。Day09 第三个代码文件聚焦style属性的使用,直接操作 DOM 元素的内联样式,弥补了 CSS 静态样式无法响应交互的不足。

2.4.1 核心原理:style 属性与 CSS 样式的映射关系

DOM 元素的style属性是一个对象,其属性名对应 CSS 样式名,但需将 CSS 的 “短横线命名” 转为 JS 的 “驼峰命名”(如 CSS 中的font-size对应 JS 中的fontSize、background-color对应backgroundColor)。通过给style属性赋值,可直接修改元素的内联样式,且优先级高于外部 CSS(Day05 曾提及内联样式优先级特性)。

2.4.2 代码实战:点击按钮修改 div 样式

第三个文件中,通过按钮点击触发changeContext()函数,获取 div 元素后修改其文本颜色和字体大小,完整逻辑解析如下:

<!DOCTYPE html>

<html>

<head>

<title>js学习</title>

<style>

.box{ /* 初始CSS样式:内边距和外边距 */

padding:20px;

margin:20px;

}

</style>

</head>

<body>

<!-- 目标div:初始文本为Hello World,拥有box类 -->

<div id="context" class="box">Hello World</div>

<!-- 点击按钮触发修改样式的函数 -->

<button onclick="changeContext()">修改css样式</button>

<script>

function changeContext(){

// 1. 通过id获取目标div元素(Day09第一部分学习的元素查找方法)

var divDemo = document.getElementById("context");

// 2. 修改style属性:动态设置内联样式

divDemo.style.color = "red"; // 文本颜色改为红色(对应CSS的color)

divDemo.style.fontSize = "20px"; // 字体大小改为20px(对应CSS的font-size)

// 拓展:可添加更多样式修改

divDemo.style.backgroundColor = "#f5f5f5"; // 背景色改为浅灰色

divDemo.style.border = "1px solid #ddd"; // 添加灰色边框

}

</script>

</body>

</html>

执行效果:点击按钮后,div 文本从默认样式变为 “红色、20px 字体、浅灰色背景 + 灰色边框”,直观体现了 JS 动态修改样式的作用。

2.4.3 注意事项与拓展场景

  • 样式单位不可省略:设置fontSize、width等需要单位的样式时,必须添加单位(如20px而非20),否则样式不生效;
  • 优先级问题:style属性设置的内联样式会覆盖外部 CSS(如.box类的样式),若需恢复默认样式,可将style属性设为空字符串(如divDemo.style.color = "");
  • 常见应用场景:表单验证(输入错误时标红输入框)、导航栏 hover 效果(JS 实现更复杂的过渡)、主题切换(点击按钮切换整体页面颜色)。

2.5 JavaScript DOM 事件:绑定与触发交互逻辑

DOM 事件是 “用户操作” 与 “JS 逻辑” 的桥梁(如点击、双击、鼠标移入等操作触发对应函数)。Day09 第四个代码文件对比了 “HTML 属性绑定事件” 和 “addEventListener 绑定事件” 两种方式,重点演示了更灵活的addEventListener方法,是实现复杂交互的基础。

2.5.1 常见 DOM 事件类型:覆盖主流用户操作

代码文件中列出了前端开发常用的鼠标事件,补充完整分类及说明如下:

事件类型

触发条件

应用场景

onclick

鼠标左键单击元素

按钮点击提交表单、跳转页面

ondblclick

鼠标左键双击元素

双击打开文件、放大图片

onmousedown

鼠标按下(未松开)时

拖拽功能的开始(如拖拽元素)

onmouseup

鼠标按下后松开时

拖拽功能的结束、确认操作

onmouseover

鼠标移入元素范围时

显示下拉菜单、图片预览

onmouseout

鼠标移出元素范围时

隐藏下拉菜单、关闭预览

oninput

输入框内容变化时(拓展)

实时搜索提示、输入字数统计

2.5.2 两种事件绑定方式:HTML 属性绑定 vs addEventListener

第四个代码文件隐性对比了两种绑定方式,二者在灵活性、可维护性上差异显著,具体分析如下:

(1)HTML 属性绑定事件(简单但不推荐)

通过在 HTML 标签中添加onclick、ondblclick等属性,直接指定触发的函数,如代码中注释的写法:

<!-- HTML标签中绑定事件:直接调用changeContext函数 -->

<button onclick="changeContext()">修改css样式</button>

<div id="context" class="box" ondblclick="alert('我被双击了')">Hello World</div>

<script>

function changeContext(){

alert("我被点中了");

}

</script>

优缺点

  • 优点:语法简单,适合快速实现简单交互;
  • 缺点:HTML 与 JS 耦合(修改函数名需同时改 HTML 和 JS)、无法给同一个事件绑定多个函数(如一个按钮点击同时触发 “提交表单” 和 “显示提示”)、动态生成的元素无法绑定(如 JS 新增的按钮无法通过此方式绑定事件)。
(2)addEventListener 绑定事件(推荐,代码文件重点演示)

通过 JS 的addEventListener方法给 DOM 元素绑定事件,将 HTML 与 JS 完全分离,支持绑定多个函数、动态元素绑定等,是开发中的主流方式。第四个文件的核心代码如下:

<div id="context" class="box">Hello World</div>

<script>

// 1. 获取目标div元素

var divContent = document.getElementById("context");

// 2. 用addEventListener绑定双击事件(ondblclick对应事件类型为'dblclick')

divContent.addEventListener('dblclick', () => {

alert("我被选中了"); // 事件触发时执行的逻辑

});

// 拓展:给同一个元素的同一个事件绑定多个函数

divContent.addEventListener('dblclick', () => {

console.log("双击事件被触发,同时打印日志"); // 第二个函数也会执行

});

</script>

语法解析

element.addEventListener(事件类型, 事件处理函数, [捕获/冒泡阶段])

  • 事件类型:需去掉on前缀(如ondblclick改为dblclick、onclick改为click);
  • 事件处理函数:可写匿名函数(如代码中的箭头函数),也可写命名函数;
  • 第三个参数(可选):布尔值,true表示捕获阶段触发,false(默认)表示冒泡阶段触发(后续事件流会深入)。

优缺点

  • 优点:HTML 与 JS 解耦(便于维护)、支持给同一个事件绑定多个函数、可通过removeEventListener移除事件(避免内存泄漏)、支持动态生成的元素绑定(后续事件委托会学习);
  • 缺点:语法稍复杂,需先获取元素再绑定。

2.5.3 实战拓展:给按钮绑定多个点击事件

以 “点击按钮同时提交表单和显示成功提示” 为例,演示addEventListener绑定多个函数的优势:

<form id="myForm">

<input type="text" name="username" placeholder="请输入用户名">

<button type="button" id="submitBtn">提交</button>

</form>

<script>

var submitBtn = document.getElementById("submitBtn");

var myForm = document.getElementById("myForm");

// 第一个点击事件处理函数:提交表单

function submitForm() {

myForm.submit(); // 提交表单

}

// 第二个点击事件处理函数:显示成功提示

function showTip() {

alert("提交成功,正在跳转...");

}

// 给按钮绑定两个点击事件:点击时同时执行两个函数

submitBtn.addEventListener('click', submitForm);

submitBtn.addEventListener('click', showTip);

</script>

执行效果:点击 “提交” 按钮,会同时触发 “表单提交” 和 “显示成功提示”,这是 HTML 属性绑定方式无法实现的。

三、表单事件

3.1 表单事件:submit 提交与默认行为阻止

表单是前端与用户交互的核心组件(如登录、注册、信息提交),Day09 第五个文件聚焦表单的submit事件,重点演示了 “表单提交验证” 与 “默认行为阻止”,这是避免页面刷新、实现异步提交的关键。

3.1.1 表单事件的核心逻辑

表单默认提交行为会触发页面刷新(传统方式将数据发送给服务器后跳转页面),但实际开发中(如 AJAX 异步提交)需先验证数据有效性,再决定是否提交。第五个文件通过addEventListener绑定submit事件,配合e.preventDefault()实现 “先验证、后提交” 的逻辑:

  • submit事件:当用户点击表单的 “提交按钮”(type="submit")或按回车键时触发;
  • e.preventDefault():阻止事件的默认行为(即阻止表单刷新提交),为自定义验证逻辑留出空间。

3.1.2 代码解析与拓展

<form id="myForm">

<input type="text" name="username" required placeholder="输入用户名" >

<button type="submit">提交</button>

<button type="reset">重置</button>

</form>

<script>

const form = document.getElementById("myForm");

// 绑定submit事件,e为事件对象

form.addEventListener("submit", (e) => {

// 1. 阻止表单默认提交行为(关键步骤,避免页面刷新)

e.preventDefault();

// 2. 自定义验证逻辑(拓展:在原代码基础上补充用户名合法性校验)

const username = form.querySelector('input[name="username"]').value;

// 验证用户名长度(如至少3个字符)

if (username.length < 3) {

alert("用户名长度不能少于3个字符,请重新输入!");

return; // 验证失败,终止后续操作

}

// 3. 验证通过,执行提交逻辑(如发送AJAX请求,后续会学习)

alert("表单验证通过,准备提交");

// 实际开发中此处会写:axios.post("/submit", { username })...

});

</script>

补充说明:

  • 表单中的required属性是 HTML5 自带的基础验证(为空时阻止提交),但仅靠前端验证不安全,需配合后端二次验证;
  • reset按钮(type="reset")无需额外 JS 逻辑,点击后会自动清空表单内所有输入框的值,适合 “重新填写” 场景。

3.2 文档 / 窗口事件:load 事件与页面资源加载监听

第六个文件演示了window对象的load事件,用于监听 “页面所有资源加载完成” 的时机,这在需要操作图片、脚本等外部资源的场景中至关重要(如图片加载完成后获取尺寸、初始化依赖外部资源的插件)。

3.2.1 load 事件的触发时机

load事件是window对象的核心事件之一,其触发时机是 “页面中所有资源(HTML 结构、CSS 样式、图片、脚本文件、字体等)完全加载完成后”,区别于DOMContentLoaded事件(仅 HTML 结构加载完成即触发,不等待图片等资源)。

第六个文件的代码逻辑:当页面中模拟的 “大图片” 及其他资源加载完成后,弹出提示框,确保后续操作不会因资源未加载而报错:

<script>

// 给window绑定load事件

window.addEventListener("load", () => {

alert("页面图片、脚本等所有资源都加载完成了");

// 拓展:此时可安全操作图片资源(如获取图片尺寸)

const img = document.querySelector("img");

console.log("图片宽度:", img.offsetWidth);

console.log("图片高度:", img.offsetHeight);

});

</script>

<!-- 模拟需要加载的外部图片(实际开发中src为真实图片地址) -->

<img src="https://example.com/large-image.jpg" alt="大图片">

3.2.2 应用场景与注意事项

  • 适用场景
  1. 图片加载完成后裁剪、压缩或获取尺寸;
  2. 初始化依赖外部脚本的插件(如地图插件、图表插件);
  3. 确保页面所有样式加载完成后再执行 DOM 样式修改,避免样式闪烁。
  • 注意事项
  1. load事件触发时机较晚,若仅需操作 HTML 结构(如给 DOM 元素绑定事件),推荐使用DOMContentLoaded事件,提升页面响应速度;
  2. 若页面中存在加载失败的资源(如图片 404),load事件仍会正常触发,不会因个别资源加载失败而阻塞。

3.2.3 拓展:DOMContentLoaded 事件对比

为了更清晰区分load与DOMContentLoaded,补充代码示例,帮助理解两者的差异:

<script>

// 1. DOMContentLoaded:HTML结构加载完成即触发(不等待图片)

document.addEventListener("DOMContentLoaded", () => {

console.log("HTML结构加载完成,可操作DOM元素");

});

// 2. load:所有资源加载完成后触发(包括图片)

window.addEventListener("load", () => {

console.log("所有资源加载完成,可操作图片等外部资源");

});

</script>

<img src="https://example.com/large-image.jpg" alt="大图片">

执行结果:先打印 “HTML 结构加载完成...”,后打印 “所有资源加载完成...”,体现了两者的触发时机差异。

四、窗口缩放和页面滚动

4.1 窗口缩放事件(resize):响应式交互的核心触发

窗口缩放事件(resize)是前端实现 “响应式交互” 的关键事件之一,当浏览器窗口的宽度或高度发生变化时会自动触发。第七个文件通过 “窗口缩放时更新尺寸显示” 的案例,演示了resize事件的基础应用,其核心价值在于适配不同设备屏幕尺寸(如 PC 端窗口缩小、移动端横屏 / 竖屏切换)时的界面调整。

4.1.1 基础语法与事件绑定

resize事件需绑定到window对象(代表浏览器窗口),通过addEventListener实现事件监听,语法结构如下:

// 绑定窗口缩放事件

window.addEventListener("resize", () => {

// 窗口缩放时执行的逻辑(如更新尺寸显示、调整DOM布局)

});

4.1.2 实战解析:窗口缩放时更新尺寸文本

第七个文件的核心逻辑是 “当窗口缩放时,修改p标签的文本内容”,但代码中固定将文本设为"200px",实际开发中更常用 “动态获取窗口实时尺寸” 的方式优化,完整优化代码如下:

// 1. 获取显示尺寸的DOM元素

const sizeText = document.getElementById("windowSize");

// 2. 定义更新尺寸的函数(复用逻辑,避免重复代码)

function updateWindowSize() {

// 获取窗口实时宽度(window.innerWidth)和高度(window.innerHeight)

const windowWidth = window.innerWidth;

const windowHeight = window.innerHeight;

// 动态更新文本内容,显示当前窗口尺寸

sizeText.textContent = `窗口宽度:${windowWidth}px,窗口高度:${windowHeight}px`;

}

// 3. 绑定窗口缩放事件:缩放时触发更新

window.addEventListener("resize", updateWindowSize);

// 4. 初始加载时执行一次:确保页面打开就显示正确尺寸

updateWindowSize();

4.1.3 关键 API:获取窗口尺寸的核心属性

  • window.innerWidth:获取浏览器窗口的 “可视区域宽度”(包含滚动条宽度,不包含浏览器边框);
  • window.innerHeight:获取浏览器窗口的 “可视区域高度”(包含滚动条高度,不包含浏览器顶部导航栏);
  • 若需排除滚动条宽度,可使用document.documentElement.clientWidth(仅可视区域,不含滚动条),需根据实际需求选择。

4.1.4 实际应用场景

  • 响应式布局调整:如窗口宽度小于 768px 时,隐藏 PC 端导航栏、显示移动端菜单;
  • 图表适配:如 ECharts 图表在窗口缩放时,调用resize()方法重新渲染图表尺寸;
  • 元素定位修正:如固定在窗口右侧的 “返回顶部” 按钮,在窗口缩小时调整右侧距离。

4.2 页面滚动事件(scroll):滚动交互的基础触发

页面滚动事件(scroll)在用户滚动页面(垂直滚动或水平滚动)时触发,第八个文件通过 “滚动页面时显示滚动距离” 的案例,演示了scroll事件的应用,其核心价值在于实现 “滚动到指定位置显示元素”“滚动进度条”“导航栏吸顶” 等常见交互效果。

4.2.1 基础语法与事件绑定

与resize事件类似,scroll事件也需绑定到window对象(或可滚动的 DOM 元素,如带overflow: auto的容器),基础语法如下:

// 绑定页面滚动事件(全局滚动)

window.addEventListener("scroll", () => {

// 页面滚动时执行的逻辑(如获取滚动距离、控制元素显示/隐藏)

});

// 绑定局部元素滚动事件(如带滚动条的div)

const scrollContainer = document.getElementById("scrollContainer");

scrollContainer.addEventListener("scroll", () => {

// 局部元素滚动时执行的逻辑

});

4.2.2 实战解析:滚动时显示垂直滚动距离

第八个文件的核心逻辑是 “滚动页面时,更新固定定位的p标签文本”,但代码中固定设为"ssss",实际开发中需 “动态获取垂直滚动距离” 并显示,完整优化代码如下:

// 1. 获取显示滚动距离的DOM元素(固定在页面右上角)

const posText = document.getElementById('scrollPos');

// 2. 定义更新滚动距离的函数

function updateScrollPosition() {

// 获取页面垂直滚动距离:window.scrollY(等价于document.documentElement.scrollTop)

const scrollDistance = window.scrollY;

// 动态更新文本内容,显示当前滚动距离

posText.textContent = `滚动距离:${scrollDistance}px`;

}

// 3. 绑定页面滚动事件:滚动时触发更新

window.addEventListener('scroll', updateScrollPosition);

// 4. 初始加载时执行一次:确保页面打开时显示初始滚动距离(0px)

updateScrollPosition();

4.2.3 关键 API:获取滚动距离的核心属性

  • 垂直滚动距离:
  • window.scrollY:返回页面从顶部开始的垂直滚动距离(单位:px),兼容性较好;
  • document.documentElement.scrollTop:与scrollY功能一致,部分旧浏览器需用此属性兼容;
  • 水平滚动距离:
  • window.scrollX(或document.documentElement.scrollLeft):返回页面从左侧开始的水平滚动距离,适用于横向滚动的页面。

4.2.4 实际应用场景

  • 滚动进度条:根据scrollY与 “页面总高度” 的比例,动态设置进度条的宽度;
  • 元素懒加载:滚动到指定位置时,才加载图片或请求数据(减少初始加载压力);
  • 导航栏吸顶:当滚动距离超过导航栏顶部时,给导航栏添加position: fixed样式,固定在页面顶部;
  • 回到顶部按钮:当滚动距离大于 500px 时显示 “回到顶部” 按钮,点击后通过window.scrollTo(0, 0)回到页面顶部。

4.2.5 性能优化:避免滚动事件高频触发

scroll事件的特点是 “高频触发”(滚动过程中每秒触发数十次),直接在事件回调中执行复杂逻辑(如 DOM 操作、数据计算)会导致页面卡顿。实际开发中可通过 “防抖(debounce)” 优化,减少事件触发次数,示例代码如下:

// 防抖函数:延迟执行回调,避免高频触发

function debounce(func, delay = 100) {

let timer = null; // 定时器标识

return function() {

clearTimeout(timer); // 每次触发时清除之前的定时器

// 延迟delay毫秒后执行函数

timer = setTimeout(() => {

func.apply(this, arguments);

}, delay);

};

}

// 用防抖函数包装更新滚动距离的逻辑,延迟100ms执行

const debouncedUpdate = debounce(updateScrollPosition);

// 绑定优化后的滚动事件

window.addEventListener('scroll', debouncedUpdate);

通过防抖优化,滚动过程中仅在 “停止滚动 100ms 后” 执行一次逻辑,大幅降低性能消耗。

五、总结

Day09 围绕 JavaScript DOM 操作展开,核心是掌握 “找到元素→修改元素→响应交互” 的完整逻辑:通过 ID、类名、标签、CSS 选择器等方式精准查找 DOM 元素,利用textContent/innerHTML和style属性分别修改元素内容与样式,再通过addEventListener绑定鼠标、表单、文档、窗口等多类事件,实现用户操作与页面反馈的联动。整套知识点串联起前端动态交互的核心流程,解决了 “如何让静态页面动起来” 的核心问题,为后续开发复杂交互功能打下坚实基础。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐