JavaScript进阶与轮播图实现 课堂笔记

第一部分:To-Do List 修改功能实现

1.1 修改功能的核心思路

老师强调:修改的本质是"覆盖"而不是"新增"。必须在原有基础上进行改动,而不是重新创建。修改操作分三步走:

  1. 定位:找到需要修改的单元格
  2. 回显:将单元格内容显示到输入框
  3. 覆盖:将输入框新值写回原单元格

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是默认值,元素按正常文档流排列。设置topleft等属性无效。

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向左移动(显示下一张)
相关推荐
专业抄代码选手18 分钟前
05|把递归渲染拆成 Fiber:让一棵大树可以暂停
前端·javascript·react.js
mayaairi22 分钟前
JS DOM节点操作完全指南:增删改查与性能优化
开发语言·javascript·性能优化
Demon--hx23 分钟前
多态实现原理
开发语言·c++
天才熊猫君24 分钟前
Vue 3 插槽机制深度解析:两条线与三层树
前端·javascript
wanglei20070826 分钟前
消息队列的协作模式
开发语言·python
李溪白29 分钟前
事件循环(Event Loop):JavaScript 里的“时间管理大师”与“插队狂魔”
javascript
mONESY31 分钟前
告别 Vibe Coding:用 SDD 把一个 Chrome 翻译插件从 0 做到 1
javascript
Sherotree34 分钟前
Agent 工程笔记①:工具调用失败时,先查哪三层
网络·数据库·笔记
xcLeigh35 分钟前
Go入门:rune与byte的区别和使用场景
android·javascript·golang