事件
事件
一、事件概述:
用户在浏览器上触发一个操作,浏览器上会执行相关的函数进行处理称为事件。
事件是一个流程,就是一个监听一个触发,整个过程的描述。
二、事件的模式
1、内联模式
<div onclick='方法名()'></div>
2、脚本模式
document.queryseletor('div').onclick = function(){
//操作
} //也会被解析为内联
内联里面调用的方法的this会指向window(传递this)脚本模式的this会指向当前的调用者
三、事件的分类
1、鼠标事件(鼠标触发的 mouse开头的都是鼠标事件)
- click 单击事件
- dblclick 双击事件
- mousemove 鼠标移动事件
- mouseover 鼠标移进 (自己及自己里面的都能触发)
- mouseout 鼠标移出
- mouseenter 鼠标移进 (只会是自己可以触发)
- mouseleave 鼠标移出
- mousedown 鼠标按下
- mouseup 鼠标弹起
<style>
div{
width: 500px;
height: 500px;background-color: pink;
}
</style>
<div>
<button>
儿子
</button>
</div>
<script>
document.onclick = function(){
console.log('单击了');
}
document.ondblclick = function(){
console.log('双击了');
}
document.onmousemove = function(){
console.log('鼠标移动');
}
var box = document.querySelector('div')
box.onmouseover = function(){//对应的子元素也可以触发
console.log('over移进');
}
box.onmouseout = function(){//对应的子元素也可以触发
console.log('out移出');
}
box.onmouseenter = function(){//只有自己能触发
console.log('enter移进');
}
box.onmouseleave = function(){//只有自己能触发
console.log('leave移出');
}
box.onmousedown = function(){
console.log('按下');
}
box.onmouseup = function(){
console.log('弹起');
}
box.onclick = function(){
console.log('点击');
}
// 鼠标右击事件(不会触发点击事件)
box.oncontextmenu = function(){
console.log('右键点击');
}
// 点里面会触发外面的元素的点击事件 这种叫事件冒泡(逐层向上冒泡)
// 除非是输入框 不然是不能调用键盘事件 都是window的
window.onkeydown = function(){
console.log('键盘按下');
}
window.onkeyup = function(){
console.log('键盘弹起');
}
window.onkeypress = function(){
console.log('字符键按下');
}
</script>
2、键盘事件(键盘触发 key开头的都是键盘事件)
- keyup 弹起
- keydown 按下
- keytpress 字符键按下
//除非是输入框 不然是不能调用键盘事件 都是window的
window.onkeydown = function(){
console.log('键盘按下');
}
window.onkeyup = function(){
console.log('键盘弹起');
}
window.onkeypress = function(){
console.log('字符键按下');
}
3、HTML事件(系统事件 被动触发的事件)
- load 加载
- close 关闭
- change 输入框的value值发送表示
- select 只有输入框才能触发 (选择里面的内容)
- focus 获取焦点
- blur 失去焦点
- reset 重置
- submit 提交
- scorll 滚动条滚动
<input type="text">
<form action="">
<button type="submit">提交</button>
<button type="reset">重置</button>
</form>
<div style="height:1500px"></div>
<script>
// load 窗口的加载 图片的加载 等等
window.onload = function(){
console.log('窗口的加载');
}
window.onunload = function(){//清除对应的内存 销毁
console.log('窗口的卸载');
}
window.onclose = function(){
console.log('窗口的关闭');
}
var input = document.querySelector('input')
input.onchange = function(){
console.log('value值变化了');
}
input.onselect = function(){
console.log('当前内容被选择了');
}
input.onfocus = function(){
console.log('获取焦点');
}
input.onblur = function(){
console.log('失去焦点');
}
document.querySelector('form').onsubmit = function(){
console.log('表单提交');
}
document.querySelector('form').onreset = function(){
console.log('表单重置');
}
window.onscroll = function(){//每次滚动的距离
console.log('滚动条滚动');
}
</script>
四、事件的组成
触发者.on+对应的事件名 = 处理的函数 对应的事件组成
触发者 一般来说是对应的元素对象
事件名 就是上述分类的事件名
处理函数 由自己定义的函数(handler)(这个函数是事件驱动执行)
五、event(事件源)
关于事件的组成 元素.on事件名 = 处理函数
- 处理函数 是一个function 作为一个function 他具备一个arguments(参数数组)
- 因为arguments[0] 是获取第一个参数 那么我在对应的处理函数里面写一个参数这个参数不就是对应的arguments[0]
- 我们发现对应的arguments[0] 返回的对应对象是一个event类型的对象 所以我们可以猜出来他设计了一个名event的对象 而这个对象同时又是全局的对象 所以他归属于window 所以我们可以写成 window.event 或者 省略对应的window(event)
//e是形参 相当于第一个形参 常见的写法 这个形参名字叫 e 或者 event
window.onkeydown = function(e){
console.log(e); //这个就是arguments[0] event类型对象
//他设计一个event对象 他是一个全局的变量 window.event
//ie为了兼容 我们会写出
e = e || window.event //兼容写法
console.log(e.altKey);
console.log(e.key);
}
六、属性
1、坐标相关的属性
- x 得到鼠标的x坐标(不包含不可视区域)
- y 得到鼠标的y坐标 (不包含不可视区域)
- pageX 得到鼠标在页面上的x坐标 (包含不可视区域)
- pageY 得到鼠标在页面上的y坐标 (包含不可视区域)
- clientX 得到鼠标在可视区域内的x坐标 (不包含不可视区域)
- clientY 得到鼠标在可视区域内的y坐标 (不包含不可视区域)
- offsetX 得到鼠标在偏移元素内容的x坐标 (当前添加事件的元素里面的坐标 不包含border)
- offsetY 得到鼠标在偏移元素内容的y坐标 (当前添加事件的元素里面的坐标 不包含border)
- layerX 默认是得到鼠标基于页面的x坐标 当你添加定位以后他是基于定位元素的坐标
- layerY 默认是得到鼠标基于页面的y坐标 当你添加定位以后他是基于定位元素的坐标
- screenX 得到鼠标在屏幕的上的x坐标
- screenY 得到鼠标在屏幕上的y坐标
<style>
*{
padding: 0;
margin: 0;
}
.box{
width: 300px;
height: 300px;
background-color: skyblue;
position: relative;
left: 20px;
top: 30px;
}
.btn{
width: 50px;
height: 50px;
background-color: pink;
position: absolute;
left: 70px;
top: 80px;
}
</style>
<div class="box">
<div class="btn">
我是按钮
</div>
</div>
<script>
document.querySelector('.btn').onclick = function(){
console.log(arguments);
console.log(arguments[0]);//取出里面的第一个元素
// 这个对象他具备一些属性 可以获取
console.log(arguments[0].x);//鼠标的x坐标 不包含不可视区域
console.log(arguments[0].y);//鼠标的y坐标
console.log(arguments[0].pageX);//页面上的x 包含不可视区域
console.log(arguments[0].pageY);//页面上的y
console.log(arguments[0].layerX);//layer默认以body作为位置定位 当你加上定位以后就是基于自己
console.log(arguments[0].layerY);
console.log(arguments[0].clientX);//当前页面的鼠标x坐标 不包含不可视区域
console.log(arguments[0].clientY);
console.log(arguments[0].offsetX);//偏移的鼠标x坐标 没有算上对应的父元素的margin以及自身的border
// 得到当前点击元素内容的坐标(当前添加事件的元素里面的坐标,基于自身)
console.log(arguments[0].offsetY);//偏移的鼠标x坐标
// 屏幕坐标
console.log(arguments[0].screenX);//屏幕的x坐标
console.log(arguments[0].screenY);//屏幕的y坐标
</script>
2、按键相关的属性
- altKey 是否长按alt键
- ctrlKey 是否长按ctrl键
- shiftKey 是否长按shift键
// 按键相关的属性 有没有按下(长按不松开)对应的键(布尔类型)
console.log(arguments[0].altKey);//有没有按下alt键
console.log(arguments[0].ctrlKey);//有没有按下ctrl键
console.log(arguments[0].shiftKey);//有没有按下shift键
3、鼠标相关的内容(只有鼠标触发的事件有)
button 返回的值为number类型(0 表示左键 1表示中间 2表示右键)
// 鼠标相关的内容
// button 返回的值为number类型(0表示左键 1表示中建 2表示右键(默认右键触发菜单,不会触发3))
console.log(arguments[0].button);
4、事件触发的相关属性
- type 事件类型 返回对应的事件名
- target 目标元素
- 返回真实触发的事件元素
- currentTarget 目标元素 返回当前添加事件的元素
- bubbles 事件是否冒泡
// 事件触发的相关属性
console.log(arguments[0].type);// 事件触发类型 返回对应事件名
console.log(arguments[0].target);//目标对象 表示事件触发真实的触发元素 子元素,自己本身
console.log(arguments[0].currentTarget);//目标对象 表示事件触发的元素(对应的加事件的元素 父元素)
console.log(arguments[0].bubbles);//是否冒泡
5、键盘事件相关的内容(需要键盘来触发的事件)
- key 属性 (当前按下的键)
- keyCode 属性 (获取当前按下键大写的ascii码)
- charCode 属性(字符键 press事件 ascii码)
// 打印完,我们可以看到argements具备一个参数 是一个对象(pointterEvent)
// 键盘相关的内容(需要键盘来触发的事件)
window.onkeydown = function(){
console.log(argumengts[0]);
console.log(arguments[0].key);//当前按下的键
console.log(arguments[0].keyCode);//当前按下的键的大写的ASCII码
console.log(arguments[0].charCode);//字符键 press 按下的是36个英文字母显示0
}
另一种写法
// e是形参 相当于第一个形参 常见的写法 这个形参的名字叫e或者叫event
window.onkeydown = function(e){
console.log(e);//这个就是arguments[0] event类型对象
// 他设计了一个event对象 他是一个全局的变量 window.event
// ie为了兼容 我们会写出
console.log(e.altKey);//兼容写法
console.log(e.key);
}
七、事件流
1、概述:
事件流指代的是事件的执行流程,多个盒子嵌套相同事件,这个时候你触发一个盒子的事件,并不会只执行一个盒子的事件的处理函数,而是全部执行。
2、事件流的两种模式
(1)冒泡模式(浏览器采用的)
冒泡模式指代的是事件从里到外逐个执行
阻止事件冒泡
- e.stopPropagation() 函数 (*)(stop)
- e.cancelBubble = true 属性设置(现在虽然都可以用 但是未来可能会废弃)
兼容写法
e.stopPropagation?e.stopPropagation():e.cancelBubble = true
(2)捕获模式
捕获模式指代的是事件从外到里逐个执行
3、默认行为
(1)概述:
就是一个元素或者标签自身带的行为称为默认行为。比如a标签的跳转,form标签的submit按钮提交之后会自动刷新页面,鼠标右击会出现一个菜单栏等一系列
有些时候我们不需要这些默认行为是产生,我们就需要阻止默认行为
(2)阻止默认行为的js实现
- e.preventDefault() 函数 (*) (prevent)
- e.returnValue = false ie的兼容
- return false 直接结束对应的操作
e.preventDefault?e.preventDefault():e.returnValue = false //兼容
4、拖拽
(1)思路:
- 给拖拽的元素添加mousedown的事件 记录当前点击的位置
- 给对应的容器添加mousemove事件 记录每次移动的位置
- 给对应的容器添加mouseup 事件 清除上述mousemove事件
(2)代码实现:
<style>
div{
width: 200px;
height: 200px;
background-color: pink;
position: absolute;
}
</style>
<div id="box"></div>
<script>
// 获取div
var box = document.getElementById('box')
// 给div添加mousedown事件
box.onmousedown = function(e){
e = e||event
// 记录鼠标在div里面的位置
// 在mousedown里面记录按下的位置
// var x = e.offsetX
// var y = e.offsetY
var x = e.pageX-box.offsetLeft
var y = e.pageY-box.offsetTop
box.onmousemove = function(e){
e=e||event
var currentX = e.pageX
var currentY = e.pageY
box.style.left = currentX-x + 'px'
box.style.top = currentY-y + 'px'
}
box.onmouseup = function(){
box.onmousemove = null
}
}
</script>
5、样式获取
style属性 只能获取标签内容style属性里面存在的一些样式
如果你需要获取对应的全局所有地方设置样式 我们就需要采用一些方法
(1)getComputedStyle 方法属于window的方法
window.getComputedStyle(元素对象,null) //返回给你的是一个样式对象
(2)ie兼容
element.currentStyle //返回给你一个样式对象
(3)兼容封装
//方法的封装
function getStyle(element,attr){
var style = window.getComputedStyle?window.getComputedStyle(element):element.currentStyle
return style[attr]
}
//调用
console.log(getStyle(box,'height'));
八、事件回顾总结
1、事件委托
概述: 将对应的子元素的事件添加给父元素,用e.target来获取真实操作的元素 从而完成相关的操作(不能用到事件委托的 mouseenter 和 mouseleave 以及 mousemove..)
//事件委托 利用父元素添加事件 通过e.target获取真实的操作元素来进行相关的操作
//当你有许多需要同时添加一个事件行为的同级元素 这个时候我们不给这些元素加事件
// 而是给他的父元素添加事件 称为事件委托
gameList.onmouseover = function(e){
e = e || event
//控制对应的li标签的背景颜色变化 得到实际的触发对象 target
if(e.target.nodeName == 'LI'){
//先排他
for(var i=0;i<games.length;i++){
this.children[i].style.backgroundColor = 'black'
}
e.target.style.backgroundColor = 'red'
}
}
// 5, 选择某一项, 将顶部的名称改成你选择的游戏名称
gameList.onclick = function(e){
e = e || event
if(e.target.nodeName == 'LI'){ //如果当前的e.target是li的话 才执行对应的操作
title.innerText = e.target.innerText
}
}
2、offset家族
- offsetParent 偏移的父元素(一层一层的向上找 找到定位的元素就是对应的父元素 有定位的上层元素
- 就他的父元素 找不到的就是body)
- offsetLeft 基于偏移的父元素的左偏移量
- offsetTop 基于偏移的父元素的上偏移量
- offsetHeight 获取偏移元素的高度(包含border以及padding)
- offsetWidth 获取偏移元素的宽度(包含border以及padding)
3、拖拽(区间拖拽)
//拖拽的方法实现 第一个是移动的盒子 第二个在哪移动
function touch(moveBox,box){
//给moveBox添加按下事件 记录一下当前鼠标在moveBox里面点击的位置
moveBox.onmousedown = function(e){
e = e || window.event
//获取对应的第一次按下的位置
var firstX = e.offsetX
var firstY = e.offsetY
// console.log(document.body.offsetParent); //偏移的父元素
//给box添加move事件 记录每次的位置 在box的位置 设置moveBox在box的定位
box.onmousemove = function(e){
e = e || event
//这个108是对应的box离body的距离 这个距离就是box偏移的距离
//offsetLeft 得到基于父元素左偏移量 offsetTop 得到基于父元素的上偏移量
//offsetParent 基于的父元素 基于定位的 他会一层层往上找 找到定位的父元素就基于
他 如果没有找到就基于body
//有奶便是娘 谁有定位他就基于谁
var currentX = e.pageX - getOffset(this).left
var currentY = e.pageY - getOffset(this).top
var targetX = currentX - firstX
var targetY = currentY - firstY
//判断边界 offsetWidth 得到盒子的宽度 offsetHeight得到盒子的高度
if(targetX<0){
targetX = 0
}
if(targetY<0){
targetY = 0
}
if(targetX>this.offsetWidth-moveBox.offsetWidth){
targetX = this.offsetWidth-moveBox.offsetWidth
}
if(targetY>this.offsetHeight-moveBox.offsetHeight){
targetY = this.offsetHeight-moveBox.offsetHeight
}
// 设置moveBox在box的定位
moveBox.style.left = targetX + 'px'
moveBox.style.top = targetY + 'px'
}
//给box添加弹起事件 清除box的move事件
document.onmouseup = function(){
box.onmousemove = null
}
}
}
4、获取对应的盒子离最外层body的left值及top值
//获取对应的元素离body的距离 传入一个元素
function getOffset(element){
var left = 0
var top = 0
while(element){
left += element.offsetLeft
top += element.offsetTop
element = element.offsetParent
}
return {left,top}
}
5、事件监听器
(1)addEventListener (添加事件监听)任何元素都能调用(观察者模式 observer)
element.addEventListener('事件名',处理函数,'是否捕获')
(2)removeEventListener (移除事件监听)任何元素都能调用
element.removeEventListener ('事件名',处理函数)
示例:
//是否捕获 默认为不捕获(冒泡)
// 同时给一个事件加多个处理函数 (事件只会调用一次)
btn.addEventListener('click',function(){
console.log('点击了');
},true)
btn.addEventListener('click',function(){
console.log('点击了1');
},true)
btn.addEventListener('click',function(){
console.log('点击了2');
},true)
btn.addEventListener('click',function hello(){
console.log('点击了3');
})
btn.removeEventListener('click',function hello(){
console.log('点击了3');
})//不能被移除
//移除事件监听器 移除事件监听器根据对应的处理函数来的
//这个俩个函数对象不是一个对象 比对出不来 所以就删不掉
//所以我们如果需要删除对应的处理函数的话 那么必须在监听的时候 就要保证这个处理函数和对应的删除的
时候的处理函数是一个
//正确示例
function sayHello(){
console.log('hello');
}
div.addEventListener('click',sayHello)
div.removeEventListener('click',sayHello)
(3)兼容写法
//移除函数
function removeEvent(obj, type, fn, useCapture){
if (obj.removeEventListener) {
obj.removeEventListener(type, fn, useCapture);
}
else {
obj.detachEvent("on"+type, fn);
}
//三元的写法 obj.removeEventListener?
obj.removeEventListener(type,fn,useCapture):obj.detachEvent("on"+type, fn);
}
//添加函数
function addEvent(obj, type, fn, useCapture){
if (obj.addEventListener) {
obj.addEventListener(type, fn, useCapture);
}
else {
obj.attachEvent("on"+type, fn);
}
//三元的写法 obj.addEventListener?
obj.addEventListener(type,fn,useCapture):obj.attachEvent("on"+type, fn);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律