大家好,我是阿赵。继续学习JavaScript的DOM,这次学习一下事件。
一、 事件和事件监听
1、 事件
事件是指系统内部发生的动作或者事情,比如单击一个按钮就是一个事件。
2、 事件监听
让程序检测是否有事件产生,一旦事件触发,立即调用一个函数做出响应,就叫做事件监听。
二、 事件三要素
1、 事件源:
谁身上发生的事件,比如是某个DOM元素。
2、 事件类型
触发了什么样的事件?比如是点击?还是鼠标滑过?
3、 事件调用函数
当事件发生了之后,要做什么事情?
三、 事件监听的不同方法
1、 on方法
语法:
元素对象.on事件 = 函数
例子:
btn.onclick = onBtnClickFun;
2、 addEventListener
语法:
元素对象.addEventListener(‘事件类型’,函数)
例子:
btn.addEventListener(‘click’,onBtnClickFun)
3、 两者区别
1. on方法
例子:
<body>
<button>请点击</button>
<script>
const btn = document.querySelector('button');
btn.onclick = () => {
console.log('你点击了按钮1');
}
btn.onclick = () => {
console.log('你点击了按钮2');
}
</script>
</body>
结果:

可以看到,btn.onclick被赋值了2次,而实际打印的只有第二次的内容。所以on方法注册事件监听,后面注册的方法会覆盖前面注册的方法。
2. addEventListener方法
例子:
<body>
<button>请点击</button>
<script>
const btn = document.querySelector('button');
btn.addEventListener('click', () => {
console.log('你点击了按钮1');
});
btn.addEventListener('click', () => {
console.log('你点击了按钮2');
});
</script>
</body>
结果:

可以看到,btn的addEventListener添加了相同的click事件2次,在结果里面,2次注册的函数都执行了,这说明了,addEventListener方式注册事件监听,是不会被覆盖的,而是可以多次绑定。
4、 回调函数
不论是on方法还是addEventListener方法,都是需要传入一个函数作为参数。这个函数就是回调函数。
5、 事件解绑
1. on方法
语法:
元素对象.on事件 = null
例子:
btn.onclick = null
2. addEventListener方法
语法:
元素对象.removeEventListener(‘事件类型’,函数)
例子:
btn.removeEventListener(‘click’,onBtnClickFun)
注意:如果注册事件addEventListener的时候使用了匿名函数,是没有办法通过removeEventListener解绑的。
四、 常用事件类型
1、 鼠标事件
例子:
<body>
<button>请点击</button>
<script>
const btn = document.querySelector('button');
btn.addEventListener('click', () => {
console.log('你点击了按钮');
});
btn.addEventListener("mouseover", () => {
console.log('你悬停在按钮上');
});
btn.addEventListener("mouseout", () => {
console.log('你移出了按钮');
});
btn.addEventListener("mousedown", () => {
console.log('你按下了按钮');
});
btn.addEventListener("mouseup", () => {
console.log('你松开了按钮');
});
btn.addEventListener("dblclick", () => {
console.log('你双击了按钮');
});
btn.addEventListener("mouseenter", () => {
console.log('你进入了按钮区域');
});
btn.addEventListener("mouseleave", () => {
console.log('你离开了按钮区域');
});
</script>
</body>
结果:

说明:
1. click
鼠标点击,包括了鼠标按下和抬起的过程。
2. mouseover
鼠标悬停在对象上
3. mouseout
鼠标移出了对象,不再悬停
4. mousedown
鼠标在对象上按下了
5. mouseup
鼠标在对象上抬起了
6. dblclick
鼠标在对象上双击
7. mouseenter
鼠标进入对象范围
8. mouseleave
鼠标离开对象范围。
2、 焦点事件
例子:
<body>
<button>请点击</button>
<script>
const btn = document.querySelector('button');
btn.addEventListener('focus', () => {
console.log('按钮获得焦点');
});
btn.addEventListener('blur', () => {
console.log('按钮失去焦点');
});
</script>
</body>
所谓的获得焦点,就是只当前被选中的对象,如果这个对象在被选中的状态变成不被选中,就是失去焦点。

3、 键盘事件
例子:
<body>
<script>
document.body.addEventListener('keydown', (e) => {
console.log(`你按下了${e.key}`);
});
document.body.addEventListener('keyup', (e) => {
console.log(`你松开了${e.key}`);
});
</script>
</body>
结果:

这里包含了2个事件:
1. keydown
键盘按下事件,可以获得按下的键的键盘值
2. keyup
键盘抬起事件,可以获得抬起的键的键盘值
当在网页里面输入
4、 文本事件
例子:
<body>
<input type="text">
<script>
const input = document.querySelector('input')
input.addEventListener('input', (e) => {
console.log(e.target.value)
})
</script>
</body>
结果:

这段是我用拼音打字法在输入框输入的回调情况,可以看出,只要按键按下,就会有回调,如果拼音组成了字或者词组,就会替代了之前的输入。
五、 事件对象
1、获取事件对象
在之前的例子里面,用到了很多时间对象,比如:
document.body.addEventListener('keydown', (e) => {
console.log(`你按下了${e.key}`);
});
在注册函数里面的参数e,就是事件的对象。
2、 事件对象常用属性
例子:
<body>
<button>请点击</button>
<script>
const button = document.querySelector('button');
button.addEventListener('click', (e) => {
console.log(`点击的目标是${e.target}`);
console.log(`事件的类型是${e.type}`);
console.log(`光标位置是${e.clientX},${e.clientY}`);
console.log(`页面位置是${e.pageX},${e.pageY}`);
console.log(`屏幕位置是${e.screenX},${e.screenY}`);
console.log(`偏移位置是${e.offsetX},${e.offsetY}`);
});
</script>
</body>
结果:

这里打印了事件对象的一些常用的属性,比如:
1. target
事件发生在谁的身上
2. type
事件的类型
3. clientX、clientY
获取光标相对于可见窗口的左上角位置。
4. pageX、pageY
获取光标相对于页面的左上角位置。
5. screenX、screenY
获取光标相对于屏幕的左上角位置。
6. offsetX、offsetY
获取光标相对于当前DOM对象左上角的位置。
7. key
这个例子没有用到,之前的keydown例子用到,当前按下键的键盘值。
需要注意的是,现在都用键盘值,而不用keycode了,两者的区别是:
同样是回车键,它的keycode是13,而键盘值key是”Enter”
六、 事件流
1、 什么是事件流
指的是事件完整执行过程中的流动路径。
在捕获事件阶段,是从大到小,也就是从父级到子级
在冒泡阶段,是从小到大,也就是从子级到父级
在实际工作中,都是使用事件冒泡为主。
2、 事件冒泡
当一个元素触发事件之后,会依次向上调用所有的父级元素的同名事件。
例子:
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#parent1 {
width: 400px;
height: 400px;
background-color: pink;
}
#parent2 {
width: 300px;
height: 300px;
background-color: purple;
}
#son {
width: 200px;
height: 200px;
background-color: skyblue;
}
</style>
</head>
<body>
<div id="parent1">
<div id="parent2">
<div id="son"></div>
</div>
</div>
<script>
const parent1 = document.getElementById('parent1');
const parent2 = document.getElementById('parent2');
const button = document.querySelector('button');
parent1.addEventListener('click', () => {
console.log(`你点击了parent1`);
})
parent2.addEventListener('click', () => {
console.log(`你点击了parent2`);
})
son.addEventListener('click', (e) => {
console.log(`你点击了son`);
})
</script>
</body>
结果:

当我点击了son之后,会发现son、parent2、parent1都触发了click事件。而执行的先后顺序是从小到大的,显示最小的son,然后到parent2,最后到最上层的parent1。
我们并不需要这种冒泡的效果,可以阻止冒泡的行为:
阻止冒泡,就是想把事件限制在当前的元素内容,不让它往上冒泡。
语法:
事件对象.stopPropagation
这个方法可以阻断事件流动传播,补光在冒泡阶段有效,在捕获阶段也有效。
例子:
还是刚才冒泡的例子,只是把son的注册事件代码改成:
son.addEventListener('click', (e) => {
console.log(`你点击了son`);
e.stopPropagation();
})
结果:

这时候再点击son,就不会再冒泡,只打印了son被点击的信息。
有些固定的事件本身是不会冒泡的,比如
mouseover和mouseout事件是有冒泡效果的,但
mouseenter和mouseleave是没有冒泡效果的。
3、 事件委托
事件委托是指利用事件流的特征,解决一些开发需求。
优点:可以减少注册的次数,提供程序的性能
原理:利用事件冒泡的特点,给父元素注册时间,当我们触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事件。
七、 阻止默认行为
例子:
<body>
<form action="www.baidu.com">
<input type="submit" value="submit">
</form>
<script>
var form = document.querySelector('form');
form.addEventListener('submit', function (e) {
e.preventDefault();
alert('form');
}, false);
</script>
</body>
说明:
如果在正常的情况下,在form表单里面去点击submit,就会把表单按照action提交。这时候,通过submit提交action就是表单的一个默认的行为。这里我给表单对象添加了submit事件的监听,然后通过
e.preventDefault()
来阻止了submit的默认行为,然后用alert弹窗来替代了默认的行为。
八、 页面事件
1、 页面加载事件
语法:
window.addEventListener(‘load’,func)
作用:等带页面所有资源加载完成,再去执行回调。
load事件不仅可以用在window上,也可以用在其他元素上,比如:
img.addEventListener(‘load’,func)
这样可以等待图片加载完成之后再去回调。
2、 DOM内容加载事件
语法:
document.addEventListener(‘DOMContentLoaded’,func)
作用:当厨师的HTML文档被完全加载和解析完成之后,无需等待样式表、图片等加载完成,就可以回调执行。
这个事件会比上面的load事件更快执行。
3、 页面滚动事件
语法:
window.addEventListener(‘scroll’,func)
作用:滚动条在滚动的时候,持续的触发事件
在这个过程中,可以获取滚动的位置:
通过事件对象获取scrollLeft和ScrollTop属性
获取的内容是元素往左、往上滚出去看不到的距离。
注意,这两个值是可以读写的,也就是可以给它赋值来指定当前滚动的位置。
4、 页面尺寸改变事件
语法:
window.addEventListener(‘resize’,func)
作用:会在窗口尺寸改变时触发。
在页面尺寸改变之后,一般需要获取当前页面的大小:
let clientWidth = document.documentElement.clientWidth
这里获取到的是元素可见部分的宽高,但不包含边框、margin和滚动条等。
如果要获取元素距离自己父级元素的左、上距离,可以用
元素.offsetLeft和offsetTop,这两个属性是只读的。
九、 移动端事件
在PC端有mouse鼠标系列的事件,在移动端,一般是使用触屏事件(touch),在Android和iOS平台都可以使用。
1、 touchstart
当手指触摸到DOM元素的时候触发
2、 touchmove
当手指在一个DOM元素上滑动的时候触发
3、 touchend
当手指从一个DOM元素上移开的时候触发

991

被折叠的 条评论
为什么被折叠?



