1. 事件监听
1.1 基本使用
- 概念: 让程序检测标签上是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为绑定事件或者注册事件。比如鼠标经过显示下拉菜单、比如点击可以播放轮播图等
- 事件监听三要素:
- 事件源: 哪个dom元素被事件触发了,所以要获取dom元素
- 事件类型: 用什么方式触发,比如鼠标单击click、鼠标经过mouseover等
- 事件调用的函数: 要做什么事
- 语法:
元素对象.addEventListener('事件类型', 要执行的函数)
- addEventListener可以对一个标签的相同事件,绑定多个回调函数,顺序执行回调函数。如
btn.addEventListener('click', func1)
、btn.addEventListener('click', func2)
- L0旧版事件监听:
btn.onclick = function () {......}
。对一个标签的相同事件,绑定多个回调函数,后面的会覆盖前面的
示例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button>点击</button>
<script>
const btn = document.querySelector('button')
btn.addEventListener('click', function () {
alert('hello world')
})
</script>
</body>
</html>
效果如下:
1.2 事件类型
- 鼠标事件: 鼠标触发
- click: 鼠标点击
- mouseenter: 鼠标经过
- mouseleave: 鼠标离开
- 焦点事件: 表单获得光标
- focus: 获得焦点
- blur: 失去焦点
- 键盘事件: 键盘触发
- Keydown: 键盘按下触发。如果键盘按着不放,会一直触发
- Keyup: 键盘抬起触
- 文本事件: 表单输入触发
- input: 用户输入事件
- change: input内容发生改变, 失去焦点但内容不改变不会触发
- audio/video事件:
- ontimeupdate: 视频/音频(audio/video)的播放位置(时间)发送改变时触发事件。可以通过
video.currentTime
获取当前播放位置(时间) - onloadeddata: 视频/音频(audio/video)刚开始加载时触发事件
- ontimeupdate: 视频/音频(audio/video)的播放位置(时间)发送改变时触发事件。可以通过
1.3 事件对象
- 概念: 事件对象是个对象,这个对象里有事件触发时的相关信息。可以根据这些信息做出相应的逻辑判断处理。例如鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息;例如用户按下哪个键盘,只有按下回车键才可以发布新闻
- 获取: 在事件绑定的回调函数的第一个参数就是事件对象
- 常见事件对象属性:
- type: 获取当前的事件类型
- clientX/clientY: 获取光标相对于浏览器可见窗口左上角的位置
- offsetX/offsetY: 获取光标相对于当前DOM元素左上角的位置
- key: 用户按下的键盘键的值
示例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<body>
<input type="text">
<script>
const input = document.querySelector('input')
input.addEventListener('keyup', function (e) {
console.log(e)
if (e.key === 'Enter') {
console.log('我要发布文章了')
}
})
</script>
</body>
</body>
</html>
选择输入框,按需回车键,控制台输出效果如下:
1.4 事件解绑
L0旧版事件解绑:直接使用null覆盖就可以。如btn.onclick = null
L2新版事件解绑:使用元素对象.removeEventListener('事件类型', 要执行的函数, 是否移除捕获阶段的触发事件)
:
- 执行函数必须是有名函数
- 默认只能移除冒泡阶段的触发事件
示例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no,maximum-scale=1.0,minimum-scale=1.0">
<title>Title</title>
</head>
<body>
<button>点击</button>
<script>
const btn = document.querySelector('button')
function func() {
alert('点我了')
}
btn.addEventListener('click', func)
// 移除按钮在冒泡阶段的点击事件
btn.removeEventListener('click', func, false)
</script>
</body>
</html>
页面效果如下。点击按钮不会出现弹窗
2. this环境对象
- 函数的调用方式不同,this指代的对象也不同
- 直接调用函数,其实相当于是
window.函数
,所以this指代window - 谁调用, this就是谁: 是判断this指向的粗略规则
- strict严格模式下,普通函数没有明确调用者为window,则this的值为undefined。如执行
fn()
,而不是window.fn()
,fn函数中的this是undefined
示例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<body>
<button>点击</button>
<script>
// 'use strict'
function fn() {
console.log(this) // window对象
}
fn() // 相当于执行window.fn()
const btn = document.querySelector('button')
btn.addEventListener('click', function () {
console.log(this) // btn对象
this.style.backgroundColor = 'red'
})
</script>
</body>
</body>
</html>
打开页面,点击按钮,效果如下:
3. 改变this指向
3.1 call()
- 使用call方法调用函数,同时指定被调用函数中this的值
- 语法:
fun.call(thisArg, arg1, arg2, ...)
- 返回值就是函数的返回值
示例:
const obj = {
uname: 'lily'
}
function fn(x) {
console.log(this) // {uname: 'lily'}
return x
}
const x = fn.call(obj, 6)
console.log(x) // 6
3.2 apply()
- 使用apply方法调用函数,同时指定被调用函数中this的值
- 语法:
fun.call(thisArg, [argsArray])
- 返回值就是函数的返回值
示例:
const obj = {
uname: 'lily'
}
function fn(x) {
console.log(this) // {uname: 'lily'}
return x
}
const arr = [6]
const x = fn.call(obj, arr)
console.log(x) // 6
console.log(Math.max.apply(null, arr)) // 6
3.3 bind()
- 使用bind方法不会调用函数,但会指定被调用函数中this的值
- 语法:
fun.bind(thisArg, arg1, arg2, ...)
- 返回值就是函数的构造函数和新的this、实参
示例:
const obj = {
uname: 'lily'
}
function fn(x) {
console.log(this) // {uname: 'lily'}
console.log(x) // 6
}
const returnFn = fn.bind(obj, 6) // 不执行函数
returnFn() // 执行函数