DOM-事件基础笔记

1. 能够给 DOM元素添加事件监听:

1. 什么是事件?

  1. 事件是在编程时系统内发生的动作或者发生的事情, 比如用户在网页上单击一个按钮
  2. 事件是在编程时系统内发生的动作或者发生的事情, 比如点击按钮 click

2. 什么是事件监听?

就是让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为 注册事件

1
2
3
4
5
6
7
8
元素.addEventListener('事件', 执行的函数)
// 1. 事件监听 绑定事件/注册事件/事件侦听
// 程序检测是否有事件 如有事件触发 立即调用函数做出响应/注册事件
let num1 = document.querySelector('button')
// 事件源.addEvenTlistener('事件', 事件处理函数)
num1.addEventListener('click', function () {
alert('您好')
})

3. 事件监听三要素:

  1. 事件源: 那个dom元素被事件触发了,要获取dom元素

  2. 事件: 用什么方式触发,比如鼠标单击 click、鼠标经过 mouseover 等

  3. 事件调用的函数: 要做什么事

  4. 事件类型要加引号

  5. 函数是点击之后再去执行,每次 点击都会执行一次

5. 淘宝点击关闭二维码

1
2
3
4
5
6
7
8
9
10
11
// 核心:利用样式的显示和隐藏完成, display:none 隐藏元素 display:block 显示元素
<div class="box">
<img src="images/1.jpg">
<i class="box1">x</i>
</div>
// 获取元素 i事件监听 触发函数/修改box样式
let num2 = document.querySelector('.box')
let num3 = document.querySelector('.box1')
num3.addEventListener('click', function () {
num2.style.display = 'none'
})

6. 随机点名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 需求:点击按钮之后,随机显示一个名字,如果没有显示则禁用按钮
<span>开始点名吧</span>
<button class="box2">点击开始点名</button>
function fn(min, max) {
return Math.floor(Math.random() * (max - min + min) + min)
}
let num4 = document.querySelector('span')
let num5 = document.querySelector('.box2')
let num6 = ['赵云', '张飞', '马超']
// 按钮 事件监听
num5.addEventListener('click', function () {
let num7 = fn(0, num6.length)
num4.innerHTML = num6[num7]
// 删除数组元素
num6.splice(num7, 1)
// 如果数组删没了 长度为0 就禁用按钮
if (num6.length === 0) {
num5.disabled = true
num5.innerHTML = '已经抽完了'
}
})

7. 随机点名案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
①点击开始按钮随机抽取数组的一个数据,放到页面中
②点击结束按钮删除数组当前抽取的一个数据
③当抽取到最后一个数据的时候,两个按钮同时禁用
// 核心:利用定时器快速展示,停止定时器结束展示
<h1>随机点名</h1>
<div class="box">
<span>名字是:</span>
<div class="name">这里显示姓名</div>
</div>
<div class="box1">
<button class="start">开始</button>
<button class="end">结束</button>
</div>
let arr = ['赵云', '张飞', '马超', '曹操']
function fn(min, max) {
return Math.floor(Math.random() * (max - min + min) + min)
}
// 1.获取元素 div 两个按钮
let num1 = document.querySelector('.name')
let num2 = document.querySelector('.start')
let num3 = document.querySelector('.end')
// 2.num4/num5 是全局变量
let num4 = 0
let num5 = 0
// 3.给按钮注册事件
num2.addEventListener('click', function () {
// 4.随机抽取数据 用定时器不断抽取
num4 = setInterval(function () {
num5 = fn(0, arr.length)
num1.innerHTML = arr[num5]
}, 30)
// 6.删除到最后一个后 禁用按钮
if (arr.length === 1) {
num2.disabled = num3.disabled = true
}
})
// 5.结束按钮注册事件 就是停止开始定时器
num3.addEventListener('click', function () {
clearInterval(num4)
arr.splice(num5, 1)
})

8. 事件监听版本

DOM L0 : 事件源.on事件 = function() { }

DOM L2 : 事件源.addEventListener(事件, 事件处理函数)

发展史:

  1. DOM L0: 是DOM的发展的第一个版本; L:level
  2. DOM L1: DOM级别1 于1998年10月1日成为W3C推荐标准
  3. DOM L2: 使用addEventListener注册事件
  4. DOM L3: DOM3级事件模块在DOM2级事件的基础上重新定义了这些事件,也添加了一些新事件类型

2. 事件类型

1.鼠标事件/鼠标触发

  • click鼠标点击、mouseenter鼠标经过、mouseleave鼠标离开

2.焦点事件/表单获得光标

  • focus获得焦点、blur失去焦点

3.键盘事件/键盘触发

  • Keydown键盘按下触发、Keyup键盘抬起触发

4.文本事件/表单输入触发

  • input用户输入事件

1. 小米搜索框案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
①开始下拉菜单要进行隐藏
②表单获得焦点 focus,则显示下拉菜单,并且文本框变色(添加类)
③表单失去焦点,反向操作
//需求:当表单得到焦点,显示下拉菜单,失去焦点隐藏下来菜单
<div class="box">
<input type="search" placeholder="小米笔记本">
<ul class="box1">
<li><a href="#">全部商品</a></li>
<li><a href="#">小米11</a></li>
<li><a href="#">小米10S</a></li>
</ul>
</div>
let num1 = document.querySelector('input')
let num2 = document.querySelector('.box1')
// 2. 事件监听 获取光标 focus mouseenter
num1.addEventListener('focus', function () {
// 3. 显示下拉菜单 文本框变色
num2.style.display = 'block'
num1.classList.add('search')
})
// 4. blur mouseleave 失去光标事件
num1.addEventListener('blur', function () {
// 隐藏下拉 文本框去色
num2.style.display = 'none'
num1.classList.remove('search')
})

2. 微博输入案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
①判断用输入事件 input
②不断取得文本框里面的字符长度
③把获得数字给下面文本框
//需求:用户输入文字,可以计算用户输入的字数
<div class="w">
<div class="box">
<img src="images/tip.png" alt=""><br>
<textarea placeholder="说点什么吧..." id="text" cols="30" rows="10" maxlength="200"></textarea>
<div>
<span class="box1">0</span>
<span>/</span>
<span>200</span>
<button id="box2">发布</button>
</div>
</div>
<div class="box3">
<ul>
</ul>
</div>
</div>
let num1 = document.querySelector('#text')
let num2 = document.querySelector('.box1')
// 1. 绑定事件 input 输入事件
num1.addEventListener('input', function () {
// console.log(num1.value.length)
// 2. 不断得到文本域里的文字长度
num2.innerHTML = num1.value.length
})

3. 全选文本框案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
①全选复选框点击,可以得到当前按钮的 checked
②把下面所有的小复选框状态checked,改为和全选复选框一致
③如果当前处于选中状态,则把文字改为取消, 否则反之
//需求:用户点击全选,则下面复选框全部选择,取消全选则全部取消,文字对应变化
<table>
<tr>
<th class="box">
<input type="checkbox" name="" id="checkall"><span class="all">全选</span>
</th>
<th>商品</th>
<th>商家</th>
<th>价格</th>
</tr>
<tr>
<td>
<input type="checkbox" name="check" class="ck">
</td>
<td>小米手机</td>
<td>小米</td>
<td>¥1999</td>
</tr>
</table>
let num1 = document.querySelector('#checkall')
let num2 = document.querySelectorAll('.ck')
let num4 = document.querySelector('.all')
// 1. 事件监听 全选按钮
num1.addEventListener('click', function () {
// 2. 把num1.checked 给下面三个ck小按钮
// console.log(num1.checked)
// 3. 三个ck按钮在伪数组里 用for遍历 依次给值
for (let num3 = 0; num3 < num2.length; num3++) {
// num2[num3].checked = true
num2[num3].checked = num1.checked
}
// 4. 当全选按钮选中状态 则改为取消HTML
if (num1.checked) {
num4.innerHTML = '取消'
} else {
num4.innerHTML = '全选'
}
})
// 5. 小按钮做法 给多个元素绑定相同事件
for (let num5 = 0; num5 < num2.length; num5++) {
num2[num5].addEventListener('click', function () {
// 6. 只要点击任何一个小按钮 都要遍历所有小按钮
for (let num6 = 0; num6 < num2.length; num6++) {
// 看看选中没有 如果有false 则退出循环 结束函数
if (num2[num6].checked === false) {
num1.checked = false
num4.innerHTML = '全选'
return
}
}
// 循环结束 代码走到这里 说明没false 都选中了 则全选按钮被选中
num1.checked = true
num4.innerHTML = '取消'
})
}

4. 购物车加减操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
①给添加按钮注册点击事件, 获取表单的value,然后自增
②解除减号的disabled状态
③给减号按钮添加点击事件,获取表单的value,然后自减
④自减结束需要判断,如果结果小于等于1 则添加上disabled状态
//需求:用户点击加号,则文本框+1,点击减号,则文本框-1,如果文本框为1,则禁用减号
<div>
<input type="text" id="box" value="1" readonly>
<input type="button" value="+" id="box1">
<input type="button" value="-" id="box2" disabled>
<div class="box3">已经是最大数量了
</div>
let num1 = document.querySelector('#box')
let num2 = document.querySelector('#box1')
let num3 = document.querySelector('#box2')
let num4 = document.querySelector('.box3')
// 点击加号 事件监听
num2.addEventListener('click', function () {
// 隐式转换
num1.value++
num3.disabled = false
if (num1.value >= 10) {
num2.disabled = true
num4.style.display = 'block'
}
})
// 点击减号 事件监听
num3.addEventListener("click", function () {
num1.value--
if (num1.value <= 1) {
num3.disabled = true
} else {
num2.disabled = false
num4.style.display = 'none'
}
})

3. 高阶函数

  1. 高阶函数可以被简单理解为函数的高级应用,JavaScript 中函数可以被当成【值】来对待,基于这个特性实现函数的高 级应用

  2. 【值】就是 JavaScript 中的数据,如数值、字符串、布尔、对象等

1. 函数表达式

  1. 函数表达式和普通函数并无本质上的区别:
  2. 普通函数的声明与调用无顺序限制,推荐做法先声明再调用
  3. 函数表达式必须要先声明再调用
1
2
3
4
5
6
7
// 高阶函数 函数高级用法 把函数当值来看
// 1. 函数表达式
let num1 = 1
let num2 = function () {
console.log(1)
}
// btn.onclick = function () {}

2. 回调函数

  1. 如果将函数 A 做为参数传递给函数 B 时,我们称函数 A 为回调函数
  2. 简单理解: 当一个函数当做参数来传递给另外一个函数的时候,这个函数就是回调函数
1
2
3
4
5
6
7
8
9
10
11
<button>点击</button>
function fn() {
document.write('你好')
}
// 此时里面就是回调函数 回头去调用的函数
// setInterval(fn, 1000)
// 点击事件也是回调函数 当点击后回头调用
let num3 = document.querySelector('button')
num3.addEventListener('click', function () {
alert('你好')
})

1. 函数表达式:

  1. 函数也是【数据】
  2. 把函数赋值给变量

2. 回调函数:

  1. 把函数当做另外一个函数的参数传递,这个函数就叫回调函数
  2. 回调函数本质还是函数,只不过把它当成参数使用
  3. 使用匿名函数做为回调函数比较常见

4. this环境对象

  1. 环境对象指的是函数内部特殊的变量 this ,它代表着当前函数运行时所处的环境
  2. 作用:弄清楚this的指向,可以让我们代码更简洁
  3. 函数的调用方式不同,this 指代的对象也不同
  4. 【谁调用, this 就是谁】 是判断 this 指向的粗略规则
  5. 直接调用函数,其实相当于是 window.函数,所以 this 指代 window
1
2
3
4
5
6
7
8
9
10
11
<button>点击</button>
function fn1() {
console.log(this)
}
// fn1()
window.fn1()
let num4 = document.querySelector('button')
num4.addEventListener('click', function () {
// num4 调用了函数 所以this指向num4
console.log(this)
})

5. 编程思想

1.排他思想

  1. 当前元素为A状态,其他元素为B状态
  2. 干掉所有人, 使用for循环
  3. 复活他自己, 通过this或者下标找到自己或者对应的元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<button class="pink">第1个</button><button>第2个</button><button>
let num1 = document.querySelectorAll('button')
for (let num2 = 0; num2 < num1.length; num2++) {
num1[num2].addEventListener('click', function () {
// this.classList.add('pink')

// 1. for循环做法 干掉所有人
// for (let num3 = 0; num3 < num1.length; num3++) {
// num1[num3].classList.remove('pink')
// }

// 2. 升级做法
// 只需找出唯一的 pink类 删除
document.querySelector('.pink').classList.remove('pink')

this.classList.add('pink')
})
}

6. Tab栏切换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
①点击当前选项卡,当前添加类,其余的兄弟移除类, 排他思想
②下面模块盒子全部隐藏,当前的模块显示
//需求:点击不同的选项卡,底部可以显示 不同的内容
<div class="wrapper">
<ul class="tab">
<li class="tab-item active">国际大牌<span></span></li>
<li class="tab-item">国妆名牌<span></span></li>
<li class="tab-item">清洁用品<span></span></li>
<li class="tab-item">男士精品</li>
</ul>
<div class="products">
<div class="main active"><a href="###"><img src="images/guojidapai.jpg"></a></div>
<div class="main"><a href="###"><img src="images/guozhuangmingpin.jpg"></a></div>
<div class="main"><a href="###"><img src="images/qingjieyongpin.jpg"></a></div>
<div class="main"><a href="###"><img src="images/nanshijingpin.jpg"></a></div>
</div>
</div>
let num1 = document.querySelectorAll('.tab .tab-item')
let num3 = document.querySelectorAll('.products .main')
// 1. 头部tab栏切换 给4个li添加点击事件
for (let num2 = 0; num2 < num1.length; num2++) {
num1[num2].addEventListener('mouseenter', function () {
// 2. 找到active类 移除掉
document.querySelector('.tab .active').classList.remove('active')
// 3. this 当前的元素添加
this.classList.add('active')

// 4. 底部隐藏模块 要写在点击事件里
document.querySelector('.products .active').classList.remove('active')
// 5. div对应序号 加上active
num3[num2].classList.add('active')
})
}

7. 点击随机显示图片

1
2
3
4
5
6
7
8
9
10
11
12
13
<input type="button" value="点击切换" id="btn"><br><br>
<img src="images/b01.jpg" width="300" id="img">
<script>
let arr = ['images/b01.jpg','images/b02.jpg','images/b02.jpg','images/b03.jpg','images/b04.jpg']
function fn(min, max) {
return Math.floor(Math.random() * (max - min + min) + min)
}
let num1 = document.querySelector('#btn')
let num2 = document.querySelector('#img')
num1.addEventListener('click', function () {
let num3 = fn(0, arr.length)
num2.src = arr[num3]
})

8. 同意协议按钮

1
2
3
4
5
6
7
8
9
10
let num1 = document.querySelector('#agree')
let num2 = document.querySelector('#registerBtn')
num1.addEventListener('click', function () {
// if (num1.checked === false) {
// num2.disabled = true
// } else {
// num2.disabled = false
// }
num2.disabled = !this.checked
})

9. 验证码倒计时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<ul>
<li>手机号: <input type="text"></li>
<li>验证码:<input type="text" class="btn">
<button id="btn1">获取验证码</button>
</li>
</ul>
let num1 = document.querySelector('#btn1')
num1.addEventListener('click', function () {
let num2 = 5
this.disabled = true
num1.innerHTML = `${num2}秒之后获取验证码`
let num3 = setInterval(function () {
num2--
num1.innerHTML = `${num2}秒之后获取验证码`
if (num2 === 0) {
clearInterval(num3)
num1.disabled = false
num1.innerHTML = '获取验证码'
}
}, 200)
})

10. 显示隐藏密码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div class="box">
<label for=""></label>
<input type="password" name="" id="btn">
</div>
let num1 = document.querySelector('label')
let num2 = document.querySelector('#btn')
let num3 = true
num1.addEventListener('click', function () {
this.classList.toggle('active')
if (num3) {
num2.type = 'text'
// num3 = false
} else {
num2.type = 'password'
// num3 = true
}
num3 = !num3
})

本节单词:

  1. addEventListener
  2. click
  3. focus
  4. blur
  5. mouseenter
  6. mouseleave
  7. input
  8. this