第一部分:To-Do List 修改功能实现
1.1 修改功能的核心思路
⭐ 老师强调:修改的本质是"覆盖"而不是"新增"。必须在原有基础上进行改动,而不是重新创建。修改操作分三步走:
- 定位:找到需要修改的单元格
- 回显:将单元格内容显示到输入框
- 覆盖:将输入框新值写回原单元格
1.2 为每行添加唯一标识(index属性)
⭐ 老师强调 :要追踪修改的是哪一行数据,必须给每个单元格添加唯一标识。就像给每个人分配身份证号,确保每个单元格都有独特的标识。
// 初始化计数器
var index = 0;
// 添加功能中
addBtn.onclick = function() {
if (infoInput.value.trim()) {
var tr = document.createElement("tr");
var tdOne = document.createElement("td");
tdOne.innerText = infoInput.value.trim();
// ⭐ 关键:为单元格添加唯一index属性
tdOne.setAttribute("index", index);
index++; // 每次添加后自增
// ... 后续组装和添加逻辑
}
};
原理图示:
表格数据:
┌─────────────────────────────────────┐
│ 事项 │ 操作 │
├─────────────────────────────────────┤
│ 今日目标1:xxx index="0" │ 完成修改删除 │ ← 第一行
│ 今日目标2:xxx index="1" │ 完成修改删除 │ ← 第二行
│ 今日目标3:xxx index="2" │ 完成修改删除 │ ← 第三行
└─────────────────────────────────────┘
1.3 修改功能完整实现
步骤1:点击"修改"按钮,回显数据
// 在添加逻辑内部,每次添加后重新绑定修改按钮
var updateList = document.getElementsByClassName("update");
for (var i = 0; i < updateList.length; i++) {
updateList[i].onclick = function() {
// 1. 定位:找到当前行的事项单元格
var target = this.parentElement.previousElementSibling;
// 2. 回显:将单元格内容填入输入框
infoInput.value = target.innerText;
// 3. 存储:记录要修改的行的index
var targetIndex = target.getAttribute("index");
updateIndex = targetIndex; // 全局变量存储
// 4. 切换按钮状态
addBtn.value = "修改";
addBtn.style.background = "#48dbfb"; // 变蓝
};
}
⭐ 老师强调 :通过
this.parentElement.previousElementSibling可以定位到当前行的第一个td(事项单元格)。就像查家族关系,得先确定你是哪家的孩子,才能找到你的堂兄弟。
步骤2:点击"修改"按钮,执行修改
addBtn.onclick = function() {
// 判断当前按钮状态
if (addBtn.value === "添加") {
// 执行添加逻辑(同上)
// ...
} else if (addBtn.value === "修改") {
// 执行修改逻辑
var text = infoInput.value.trim();
if (text) {
// 1. 查找所有td
var tdList = document.querySelectorAll("tbody td");
// 2. 遍历查找匹配index的单元格
for (var i = 0; i < tdList.length; i++) {
if (tdList[i].getAttribute("index") == updateIndex) {
// 3. 更新内容
tdList[i].innerText = text;
break;
}
}
// 4. 重置状态
infoInput.value = "";
addBtn.value = "添加";
addBtn.style.background = "#feca57"; // 恢复黄色
updateIndex = -1; // 清空记录的index
}
}
};
1.4 功能区分:通过按钮值判断
⭐ 老师强调 :通过监听按钮的文本内容("添加"或"修改")来判断执行相应的操作,从而实现同一按钮的不同功能。
// 伪代码逻辑
if (按钮的值 === "添加") {
执行添加操作();
} else if (按钮的值 === "修改") {
执行修改操作();
}
| 按钮状态 | 值 | 背景色 | 执行操作 |
|---|---|---|---|
| 默认 | "添加" | 黄色 #feca57 |
新增待办事项 |
| 修改模式 | "修改" | 蓝色 #48dbfb |
更新已有事项 |
1.5 修改功能完整流程图
用户点击"修改"按钮
│
▼
┌─────────────────────────┐
│ 1. 获取当前行单元格内容 │ ← this.parentElement.previousElementSibling
│ 2. 回显到输入框 │ ← infoInput.value = 单元格内容
│ 3. 记录该行的index值 │ ← updateIndex = target.getAttribute("index")
│ 4. 切换按钮状态 │ ← addBtn.value = "修改",变蓝色
└─────────────────────────┘
│
▼
用户修改输入框内容,点击"修改"按钮
│
▼
┌─────────────────────────┐
│ 1. 判断按钮值 === "修改" │
│ 2. 遍历所有td │
│ 3. 匹配index属性 │
│ 4. 更新单元格内容 │
│ 5. 重置按钮状态 │ ← addBtn.value = "添加",恢复黄色
│ 6. 清空输入框 │
└─────────────────────────┘
第二部分:JavaScript 定时器
2.1 定时器类型对比
| 定时器 | 函数 | 执行方式 | 停止方法 |
|---|---|---|---|
| 周期定时器 | setInterval() |
每隔指定时间重复执行 | clearInterval() |
| 延迟定时器 | setTimeout() |
等待指定时间后执行一次 | clearTimeout() |
⭐ 老师强调:周期定时器就像设置了闹钟,到点就会自动触发,除非手动关闭;延迟定时器则像定时炸弹,倒计时结束后只触发一次。
2.2 setInterval ------ 周期定时器
// 基本语法
var timerId = setInterval(函数, 间隔毫秒数);
// 示例:每隔1秒打印一次
var i = 0;
var timer = setInterval(function() {
i++;
console.log("第" + i + "次执行");
}, 1000);
// 停止定时器
clearInterval(timer);
⭐ 老师强调 :
setInterval()会返回一个整数类型的ID,这个ID是用来精准控制要停止哪个定时器的"身份证"。就像停车场里同时有多辆车,你必须知道具体车牌号才能让指定的车开走。
定时器ID示例:
var timer1 = setInterval(func1, 1000); // 返回 1
var timer2 = setInterval(func2, 2000); // 返回 2
var timer3 = setInterval(func3, 3000); // 返回 3
// 停止指定的定时器
clearInterval(timer2); // 只停止timer2,timer1和timer3继续运行
2.3 条件停止定时器
var i = 0;
var timer = setInterval(function() {
i++;
console.log(i);
// 当i >= 5时停止定时器
if (i >= 5) {
clearInterval(timer);
console.log("定时器已停止");
}
}, 1000);
// 输出:1, 2, 3, 4, 5, "定时器已停止"
⭐ 老师强调 :定时器的停止逻辑要写在定时器内部。如果写在外部,可能会导致程序无法按预期停止。就像把闹钟的关闭按钮装在门外,那在床上就关不掉闹钟了。
2.4 setTimeout ------ 延迟定时器
// 基本语法
var timerId = setTimeout(函数, 延迟毫秒数);
// 示例:3秒后执行一次
var timer = setTimeout(function() {
console.log("3秒后执行");
}, 3000);
// 停止延迟定时器
clearTimeout(timer);
2.5 函数引用 vs 函数调用 ------ 重要区别
⭐ 老师强调:这是初学者最容易混淆的概念!
| 写法 | 含义 | 效果 |
|---|---|---|
change |
函数引用(函数本身) | 把函数作为值传递,不执行 |
change() |
函数调用(执行函数) | 立即执行函数,返回结果 |
function change() {
console.log("hello");
return "world";
}
// 函数引用:不执行,只传递函数本身
var a = change; // a = 函数体代码
console.log(a); // 输出函数定义
// 函数调用:立即执行
var b = change(); // 输出"hello",b = "world"
console.log(b); // 输出"world"
// ⭐ 定时器正确用法:传函数引用
setInterval(change, 1000); // ✅ 每隔1秒执行一次
// ❌ 错误用法:传函数调用
setInterval(change(), 1000); // change()立即执行,返回值不是函数,报错
⭐ 老师强调 :定时器场景下,必须用
change而不是change(),否则会立即执行而非周期性触发。就像闹钟的"设定"和"响铃"是两个不同动作。
第三部分:CSS 定位技术
3.1 定位属性概述
| 定位值 | 参照物 | 是否脱离文档流 | 是否随滚动滚动 |
|---|---|---|---|
static |
无(默认) | ❌ 不脱离 | ✅ 滚动 |
relative |
自身原始位置 | ❌ 不脱离(保留空间) | ✅ 滚动 |
absolute |
最近定位祖先元素 | ✅ 脱离 | ✅ 滚动 |
fixed |
浏览器视口 | ✅ 脱离 | ❌ 固定 |
3.2 static ------ 默认定位
/* 默认状态,不参与定位 */
div {
position: static;
}
⭐ 老师强调 :
static是默认值,元素按正常文档流排列。设置top、left等属性无效。
3.3 relative ------ 相对定位
/* 相对自身原始位置偏移,保留原有空间 */
.father {
position: relative;
top: 30px; /* 向下移动30px */
left: 20px; /* 向右移动20px */
}
效果图示:
原始位置: 偏移后:
┌─────────────┐ ┌─────────────┐
│ 紫色元素 │ │ 紫色元素 │ ← 保留原始空间
└─────────────┘ └─────────────┘
│
▼ 向下30px
┌─────────────┐
│ 蓝色元素 │ ← 相对自己偏移
└─────────────┘
⭐ 老师强调 :相对定位的元素移动时,会保留原本的空间位置 ,其他元素不会填补这个空位。移动是相对于自己原来的位置进行的(
top:30px就是向下移动30像素)。
3.4 absolute ------ 绝对定位
/* 相对于最近的定位祖先元素定位,脱离文档流 */
.father {
position: relative; /* 父元素作为参照物 */
width: 400px;
height: 300px;
}
.child {
position: absolute;
right: 150px; /* 距父容器右侧150px */
bottom: 20px; /* 距父容器底部20px */
}
参照物规则:
| 情况 | 参照物 |
|---|---|
| 父元素有定位(relative/absolute/fixed) | 最近的定位父元素 |
| 所有父元素都无定位 | 浏览器视口 |
⭐ 老师强调 :绝对定位的元素会脱离文档流 (释放原有空间),其定位参照物取决于最近的定位祖先元素 。父元素设为
relative,子元素用absolute时,子元素的偏移基准会变成父元素。
3.5 fixed ------ 固定定位
/* 相对于浏览器视口固定,不随滚动移动 */
div {
position: fixed;
bottom: 20px; /* 距视口底部20px */
right: 150px; /* 距视口右侧150px */
}
⭐ 老师强调 :
fixed定位的元素会脱离文档流,不再占据原有空间,其他元素会重新排列。它会始终固定在浏览器视口的指定位置,不随页面滚动而移动。
3.6 定位参照物图示
浏览器视口(fixed的参照物)
┌─────────────────────────────────────────────┐
│ ┌─────────────────────────────────────┐ │
│ │ 父容器 (relative) │ │
│ │ ┌─────────────────────────────┐ │ │
│ │ │ 子元素 (absolute) │ │ │
│ │ │ 参照父容器定位 │ │ │
│ │ └─────────────────────────────┘ │ │
│ └─────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────┐ │
│ │ 固定元素 (fixed) │ │ ← 固定在视口,不滚动
│ │ 参照浏览器视口定位 │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
3.7 z-index ------ 层级控制
⭐ 老师强调 :
z-index用于控制定位元素的堆叠层级,数值越大,层级越高,位于上层 。使用z-index的前提是元素必须设置了除static以外的定位方式。
/* 默认:后写的元素覆盖先写的 */
.blue {
position: relative;
z-index: 2; /* 数值大 → 在上层 */
}
.purple {
position: relative;
z-index: 1; /* 数值小 → 在下层 */
}
| 条件 | 是否生效 |
|---|---|
position: static + z-index |
❌ 不生效 |
position: relative + z-index |
✅ 生效 |
position: absolute + z-index |
✅ 生效 |
position: fixed + z-index |
✅ 生效 |
第四部分:轮播图实现原理
4.1 核心思想:胶卷模型
⭐ 老师强调:轮播图的实现原理就像一长串胶卷------把多张图片连成一排("胶卷"),通过一个固定大小的"窗口"(可视区域)来查看,每次只显示一张图片。
┌─────────────────────────────────────────────────────────────┐
│ 胶卷(所有图片连成一排) │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 图片1 │ │ 图片2 │ │ 图片3 │ │ 图片4 │ │
│ │ 800×400 │ │ 800×400 │ │ 800×400 │ │ 800×400 │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
│ ▲ │
│ │ │
│ 窗口(只显示当前一张) │
│ ┌─────────┐ │
│ │ 图片1 │ ← 可见区域 │
│ └─────────┘ │
└─────────────────────────────────────────────────────────────┘
4.2 关键技术点
| 技术 | 作用 |
|---|---|
overflow: hidden |
隐藏超出窗口的内容,形成"窗口" |
position: relative(父容器) |
为子元素提供定位参照 |
position: absolute(胶卷) |
让胶卷可以相对父容器平移 |
left 属性变化 |
控制胶卷左右移动,切换显示图片 |
setInterval 定时器 |
自动每隔固定时间切换图片 |
4.3 HTML 结构
<div class="container"> <!-- 窗口:固定大小,overflow:hidden -->
<div class="film"> <!-- 胶卷:包含所有图片 -->
<img src="img1.png"> <!-- 每张图片尺寸相同 -->
<img src="img2.png">
<img src="img3.png">
<img src="img4.png">
</div>
</div>
4.4 CSS 样式
/* 1. 窗口:固定尺寸,隐藏溢出 */
.container {
width: 800px;
height: 400px;
overflow: hidden; /* ⭐ 关键:隐藏超出部分 */
position: relative; /* 作为胶卷的参照物 */
margin: 0 auto;
}
/* 2. 胶卷:所有图片排成一行 */
.film {
position: absolute; /* 相对父容器定位 */
left: 0; /* 初始位置:显示第一张 */
width: 3200px; /* 4张图片 × 800px */
height: 400px;
}
/* 3. 每张图片浮动或行内排列 */
.film img {
float: left; /* 横向排列 */
width: 800px;
height: 400px;
}
位置与显示关系:
left 值 |
显示图片 |
|---|---|
0 |
图片1(第1张) |
-800px |
图片2(第2张) |
-1600px |
图片3(第3张) |
-2400px |
图片4(第4张) |
4.5 JavaScript 自动切换
window.onload = function() {
var film = document.querySelector(".film");
var index = 0; // 当前显示第几张(从0开始)
var total = 4; // 总图片数
var width = 800; // 每张图片宽度
// 每隔3秒切换一次
setInterval(function() {
index++; // 切换到下一张
// 循环:到最后一张后回到第一张
if (index >= total) {
index = 0;
}
// 移动胶卷
film.style.left = -index * width + "px";
// 第0张:left: 0px
// 第1张:left: -800px
// 第2张:left: -1600px
// 第3张:left: -2400px
}, 3000);
};
4.6 轮播图完整示例
<!DOCTYPE html>
<html>
<head>
<style>
* { margin: 0; padding: 0; }
.container {
width: 800px;
height: 400px;
overflow: hidden;
position: relative;
margin: 50px auto;
}
.film {
position: absolute;
left: 0;
width: 3200px; /* 4张 × 800px */
height: 400px;
transition: left 0.5s ease; /* 平滑过渡动画 */
}
.film img {
float: left;
width: 800px;
height: 400px;
}
</style>
</head>
<body>
<div class="container">
<div class="film">
<img src="img1.png" alt="图片1">
<img src="img2.png" alt="图片2">
<img src="img3.png" alt="图片3">
<img src="img4.png" alt="图片4">
</div>
</div>
<script>
window.onload = function() {
var film = document.querySelector(".film");
var index = 0;
var total = 4;
var width = 800;
setInterval(function() {
index = (index + 1) % total; // 0→1→2→3→0循环
film.style.left = -index * width + "px";
}, 3000);
};
</script>
</body>
</html>
4.7 轮播图核心公式
当前显示的图片索引:index(从0开始)
胶卷偏移量:left = -index × 单张图片宽度
图片切换循环:
index = (index + 1) % 总图片数
4.8 overflow 属性详解
⭐ 老师强调 :
overflow属性只对已设置尺寸的父元素生效。若父元素未设固定高度,默认会随内容撑开,这时隐藏效果就无效了。
| 属性值 | 效果 |
|---|---|
visible |
默认,溢出内容可见 |
hidden |
溢出内容隐藏 |
scroll |
显示滚动条 |
auto |
需要时显示滚动条 |
附录一:定位属性速查表
| 定位值 | 参照物 | 脱离文档流 | 保留空间 | 滚动行为 |
|---|---|---|---|---|
static |
无 | ❌ | ✅ | 随页面滚动 |
relative |
自身原始位置 | ❌ | ✅ | 随页面滚动 |
absolute |
最近定位祖先 | ✅ | ❌ | 随页面滚动 |
fixed |
浏览器视口 | ✅ | ❌ | 固定不动 |
常见定位组合
父容器 (relative) ← 为子元素提供参照
└── 子元素 (absolute) ← 相对于父容器定位
⭐ 老师强调 :父元素设为
relative(不脱离文档流),子元素用absolute(脱离文档流),这是最常用的定位组合。
附录二:定时器速查表
| 定时器 | 创建方法 | 停止方法 | 执行次数 |
|---|---|---|---|
| 周期定时器 | setInterval(func, ms) |
clearInterval(id) |
无限(直到停止) |
| 延迟定时器 | setTimeout(func, ms) |
clearTimeout(id) |
1次 |
// 周期定时器
var timer = setInterval(function() {
console.log("每2秒执行");
}, 2000);
// 延迟定时器
var timer = setTimeout(function() {
console.log("3秒后执行一次");
}, 3000);
附录三:核心易错点速查表
| 类别 | 易错点 | 正确理解 |
|---|---|---|
| 修改功能 | 以为修改是重新创建 | 修改是"覆盖"原有内容 |
| 唯一标识 | 忘记给动态元素加标识 | 用index属性记录每行唯一ID |
| 按钮状态切换 | 修改后忘记重置按钮 | 修改完成要重置为"添加"状态 |
| 定时器函数 | setInterval(change(), 1000) |
应该传函数引用change,不是调用change() |
| 定时器停止 | 在定时器外部调用clearInterval |
停止逻辑应写在定时器内部 |
| relative空间 | 以为relative会释放空间 | relative保留原始空间 |
| absolute参照 | 以为absolute始终相对浏览器 | 参照最近定位祖先元素 |
| z-index生效条件 | 以为所有元素都能用z-index | 必须设置定位(非static) |
| overflow生效 | 以为父元素不设尺寸也能生效 | 父元素必须有固定宽高 |
| 胶卷宽度计算 | 忘记计算总宽度 | 总宽度 = 图片数 × 单张宽度 |
| left偏移方向 | 搞混正负方向 | left: -800px向左移动(显示下一张) |