什么是事件?
文档(html元素及document)或者浏览器的窗口发生的一些特定的交互瞬间;可以监听这些事件,来实现在事件发生时执行特定的操作;
元素天生自带的默认行为,不论我们是否给其绑定了方法,当我们操作的时候,也会把对应的事件触发;
let btn = document.querySelector('.btn');
let box = document.querySelector('.box');
常用的事件行为
[鼠标事件]
- click 点击(移动端click被识别为单击)
- dblclick 双击
- mousedown 鼠标按下
- mouseup 鼠标抬起
- mousemove 鼠标移动
- mouseover 鼠标滑过
- mouseout 鼠标滑出
- mouseenter 鼠标进入
- mouseleave 鼠标离开
- onmousewheel 鼠标滚轮滚动
[键盘事件]
一般input、textarea、document.body、document、window、document.documentElement 监听键盘事件
- keydown 按下某个键
- keyup 抬起某个键
- keypress 除Shift/Fn/CapsLock键以外,其它键按住(连续触发)
let input = document.querySelector('#input');
input.onkeydown = function () {
console.log('123')
};
document.onkeyup = function () {
console.log('keyup')
};
window.onkeydown = function () {
console.log('window key down')
};
/=>键盘事件对象
code & key:存储的都是按键,code更细致 // code: "KeyF" key: "F"
keyCode & which:存储的是键盘按键对应的码值 // keyCode: 70 which: 70
方向键:37 38 39 40 =>左上右下
空格SPACE 32
回车ENTER 13
回退BACK 8
删除DEL 46
SHIFT 16
CTRL 17
ALT 18
[移动端手指事件]
- touchstart 手指按下
- touchmove 手指移动
- touchend 手指松开
- touchcancel 操作取消(一般应用于非正常状态下操作结束)
多手指事件模型 Gesture
- gesturestart
- gesturechange / gestureupdate
- gestureend
- gesturecancel
[表单元素常用事件]
oninput input、textarea 等元素的输入事件
- onfocus 获取焦点(光标)事件
- onblur 失去焦点时触发
- onchange 事件,表单的值(value)发生改变时触发
input.onfocus = function () {
console.log('获取焦点')
};
input.onblur = function () {
console.log('失去焦点')
};
input.oninput = function () {
console.log(this.value);
};
[系统事件]
- window.onload 页面中所有的资源全部加载完触发
- window.onresize 当前窗口尺寸发生改变时触发
- window.onsroll 滚动条滚动时触发
- unload 资源卸载
- beforeunload 当前页面关闭之前
- error 资源加载失败
- scroll 滚动事件
- readystatechange AJAX请求状态改变事件
- contextmenu 鼠标右键触发
window.onresize = function () {
console.log('变了、变了');
};
[音视频常用事件]
- canplay 可以播放(资源没有加载完,播放中可能会卡顿)
- canplaythrough 可以播放(资源已经加载完,播放中不会卡顿)
- play 开始播放
- playing 播放中
- pause 暂停播放
DOM0
元素.on事件行为 = function(){}
DOM0事件绑定的原理:
给元素的私有属性赋值,当事件触发,浏览器会帮我们把赋的值执行,但是这样也导致 “只能给当前元素某一个事件行为绑定一个方法”
box.onclick = function () {console.log('哈哈哈')};
box.onclick = function () {console.log('呵呵呵')};
// 每次点击只输出呵呵呵
清除直接设置为null即可
box.onclick = function () {console.log('呵呵呵')
box.onclick = null;
};
box.onclick = function () {
console.log('哈哈哈~~');
//=>移除事件绑定:DOM0直接赋值为null即可
box.onclick = null;
}
DOM2
事件绑定:
ele.addEventListener('不带on的事件名',函数,是否捕获)
事件解除:(重要的是解除绑定)
ele.removeEventListener('不带on的事件名',有名函数(和绑定函数一个地址),是否捕获)
DOM2事件绑定的原理:
基于原型链查找机制,找到EventTarget.prototype上的方法并且执行,此方法执行,会把给当前元素某个事件行为绑定的所有方法,存放到浏览器默认的事件池中(绑定几个方法,会向事件池存储几个),当事件行为触发,会把事件池中存储的对应方法,依次按照顺序执行 “给当前元素某一个事件行为绑定多个不同方法”
box.addEventListener('click', function () {
console.log('哈哈哈~~');
}, false);
box.addEventListener('click', function () {
console.log('呵呵呵~~');
}, false);
点击一次,输出2次内容 哈哈哈~~ 呵呵呵~~
//DOM2事件绑定的时候,我们一般都采用实名函数
//>目的:这样可以基于实名函数去移除事件绑定
function fn() {
console.log('哈哈哈~~');
//=>移除事件绑定:从事件池中移除,所以需要指定好事件类型、方法等信息(要和绑定的时候一样才可以移除)
box.removeEventListener('click', fn, false);
}
box.addEventListener('click', fn, false);
//false表示在冒泡阶段执行此方法,true表示在捕获阶段执行此方法,默认为false
DOM0只能在目标阶段和冒泡阶段触发执行;
DOM2可以控制在捕获阶段触发;
练习一下
function fn1() { console.log(1); }
function fn2() { console.log(2); }
function fn3() { console.log(3); }
function fn1() { console.log(1); }
function fn2() { console.log(2); }
function fn3() { console.log(3); }
box.onclick = fn1
box.onclick = fn2
box.addEventListener('click', fn2, false);
box.addEventListener('click', fn3, true);
box.addEventListener('click', fn1, false);
box.onclick = function(){console.log('哈哈哈~');}
box.addEventListener('click', fn2, true);
//=>基于addEventListener向事件池增加方法,存在去重的机制 “同一个元素,同一个事件类型,在事件池中只能存储一遍这个方法,不能重复存储”
box.addEventListener('click', fn1, false);
box.addEventListener('mouseover', fn1, false);
box.addEventListener('click', function () {
console.log('哔咔哔咔~~');
});
box.onclick = function () {
console.log('哇咔咔~~');
}
box.addEventListener('click', function () {
console.log('call~~');
});
/* DOM0中能做事件绑定的事件行为,DOM2都支持;DOM2里面一些事件,DOM0不一定能处理绑定,例如:transitionend、DOMContentLoaded... */
box.style.transition = 'opacity 1s';
box.ontransitionend = function () {
console.log('哇咔咔~~');
}
box.addEventListener('transitionend', function () {
console.log('哇咔咔~~');
});
window.onload VS $(document).ready()有什么区别
window.addEventListener('load', function () {
//=>所有资源都加载完成触发
console.log('LOAD');
});
window.addEventListener('DOMContentLoaded', function () {
//=>只要DOM结构加载完就会触发
console.log('DOMContentLoaded');
});
$(document).ready(function(){})
$(function () {
//=>JQ中的这个处理(DOM结构加载完触发)采用的就是DOMContentLoaded事件,并且依托DOM2事件绑定来处理,所以同一个页面中,此操作可以被使用多次
});
//JQ中的事件绑定采用的都是DOM2事件绑定,例如:on/off/one */
let $box = $('#box');
$box.one('click', function () {
console.log('哇咔咔~~');
});
$box.on('click', function () {
console.log('哇咔咔~~');
});
$box.on('click', function () {
console.log('哔咔哔咔,丘~~');
});
1、
$(document).ready()
采用的是DOM2事件绑定,监听的是DOMContentLoaded
这个事件,所以只要DOM结构加载完成就会被触发执行,而且同一个页面中可以使用多次(绑定不同的方法,因为基于DOM2事件池绑定机制完成的);2、
window.onload
必须等待所有资源都加载完成才会被触发执行,采用DOM0事件绑定,同一个页面只能绑定一次(一个方法),想绑定多个也需要改为window.addEventListener('load', function () {})DOM2绑定方式;
事件对象和事件传播机制
给元素的事件行为绑定方法,当事件行为触发方法会被执行,不仅被执行,而且还会把当前操作的相关信息传递给这个函数 =>“事件对象”
- 如果是鼠标操作,获取的是MouseEvent类的实例 =>鼠标事件对象
- 鼠标事件对象 -> MouseEvent.prototype -> UIEvent.prototype -> Event.prototype -> Object.prototype
- 如果是键盘操作,获取的是KeyboardEvent类的实例 =>键盘事件对象
- 除了以上还有:普通事件对象(Event)、手指事件对象(TouchEvent)等
事件对象和函数以及给谁绑定的事件没啥必然关系,它存储的是当前本次操作的相关信息,操作一次只能有一份信息,所以在哪个方法中获取的信息都是一样的;第二次操作,存储的信息会把上一次操作存储的信息替换掉...;
每一次事件触发,浏览器处理机制
- 捕获到当前操作的行为(把操作信息获取到),通过创建MouseEvent等类的实例,得到事件对象EV
- 通知所有绑定的方法(符合执行条件的)开始执行,并且把EV当做实参传递给每个方法,所以在每个方法中得到的事件对象其实是一个
......- 后面再重新触发这个事件行为,会重新获取本次操作的信息,用新的信息替换老的信息,然后继续之前的步骤...