事件的基础
JavaScript的事件是由访问web页面的用户引起的一系列操作。当用户执行某些操作的时候,再去执行一系列代码,或者用来获取事件的详细信息,如鼠标位置,键盘按键等等
JavaScript可以处理的事件分为鼠标事件,键盘事件,html事件。所有的事件处理函数都会分成两部分,on+事件名称。
- onchange -> HTML 元素改变
- onclick -> 用户点击 HTML 元素
- onmouseover -> 用户在一个HTML元素上移动鼠标
- onmouseout -> 用户从一个HTML元素上移开鼠标
- onkeydown -> 用户按下键盘按键
- onload -> 浏览器已完成页面的加载
事件对象
当触发某个事件的时候,会产生一个事件对象,这个对象包含着所有与事件有关的信息。包括导致事件的元素,事件的类型,以及其他与特定事件相关的信息。
通过事件绑定的执行函数是可以得到一个隐藏函数的。说明,浏览器会自动分配一个参数,这个参数其实就是event对象。
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function(e){
var div = document.getElementById("div1");
div.onclick = function(e){ // 在参数中,会自动有一个默认隐藏的事件对象参数,用到的话就可以把他写出来,否则可以不写
console.log(window.event);
// 但是在ie中不适用,ie中获取的方法是window.event,谷歌也可以使用window.event
var evt = e || window.event ; // 创建一个变量evt保存
}
}
</script>
</head>
<body>
<div id="div1">dasdasdas</div>
</body>
</html>
clientX和clientY的使用小样例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#div1{
position: relative;
width: 500px;
height: 500px;
border: 1px black solid;
}
#span1{
position: absolute;
bottom: 0px;
}
</style>
<script>
window.onload = function(){
var div = document.getElementById("div1");
var span = document.getElementById("span1");
div.onmousemove = function(e){
var evt = e || window.event;
var x = evt.clientX;
var y = evt.clientY;
span.innerHTML = x+","+y+"px";
}
div.onmouseout = function(){
span.innerHTML = " ";
}
}
</script>
</head>
<body>
<div id="div1">
<span id="span1"></span>
</div>
</body>
</html>
键盘事件:
在 JavaScript 中,当用户操作键盘时,会触发键盘事件,键盘事件主要包括下面 3 种类型:
- keydown:在键盘上按下某个键时触发。如果按住某个键,会不断触发该事件,但是 Opera 浏览器不支持这种连续操作。该事件处理函数返回 false 时,会取消默认的动作(如输入的键盘字符,在 IE 和 Safari 浏览器下还会禁止keypress 事件响应)。
- keypress:按下某个键盘键并释放时触发。如果按住某个键,会不断触发该事件。该事件处理函数返回 false 时,会取消默认的动作(如输入的键盘字符)。
- keyup:释放某个键盘键时触发。该事件仅在松开键盘时触发一次,不是一个持续的响应状态。
键盘事件属性
键盘定义了很多属性,如下表所示。利用这些属性可以精确控制键盘操作。键盘事件属性一般只在键盘相关事件发生时才会存在于事件对象中,但是 ctrlKey 和 shiftKey 属性除外,因为它们可以在水保事件中存在。例如,当按下 Ctrl 或Shift 键时单击鼠标操作。
- keyCode 该属性包含键盘中对应键位的键值
- charCode 该属性包含键盘中对应键位的 Unicode 编码,仅 DOM 支持
- target 发生事件的节点(包含元素),仅 DOM 支持
- srcElement 发生事件的元素,仅 IE 支持
- shiftKey 是否按下 Shift 键,如果按下返回 true,否则为false
- ctrlKey 是否按下 Ctrl 键,如果按下返回 true,否则为false
- altKey 是否按下 Alt 键,如果按下返回 true,否则为false
- metaKey 是否按下 Mtea 键,如果按下返回 true,否则为false,仅 DOM 支持
charCode与keyCode的区别
onkeydown: e.keyCode 有值
onkeyup: e.keyCode 有值
onkeypress: e.keyCode 为0
onkeydown: e.charCode 为0
onkeyup: e.charCode 为0
onkeypress: e.charCode 有值
结论:charCode 返回onkeypress事件触发键值的字母代码。keyCode 返回 onkeydown 或 onkeyup 事件的键的代码
JS的事件流的概念
DOM事件流,"DOM2事件流"规定的事件流包括三个阶段:事件捕获阶段,处于目标阶段,事件冒泡阶段。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#outer{
width: 200px;
height: 200px;
background-color: red;
}
#inner{
width: 100px;
height: 100px;
background-color: blue;
}
</style>
<script>
window.onload = function(){
var outer = document.getElementById("outer");
var innner = document.getElementById("inner");
outer.onclick = function(){
console.log("outer");
}
/*
如果这样定义inner的点击事件的话,当inner被单击的时候,会向上冒泡给父级的outer
父级的事件也会被触发,控制台会先输出inner,接着输出outer。所以我们必须想办法阻止冒泡
inner.onclick = function(){
console.log("inner");
}
*/
inner.onclick = function(e){
var evt = e || event;
console.log("inner");
// 方法1
evt.cancelBubble = true;
// 方法2 现代浏览器常用
evt.stopPropagation();
}
}
</script>
</head>
<body>
<div id="outer">
<div id="inner">
</div>
</div>
</body>
</html>
事件委托机制:利用事件冒泡的原理,把本应添加给某元素上的事件委托给她的父级(外层)。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
li{
margin: 10px;
background-color: red;
}
</style>
<script>
window.onload = function(){
var oul = document.getElementsByTagName("ul")[0];
var oli = document.getElementsByTagName("li");
// 事件委托函数,把原本点击li产生的事件委托给ul
oul.onclick = function(e){
var evt = e || event; // 保证兼容性
var _target = evt.target || evt.srcElement; // 保证兼容性
if(_target.nodeName.toUpperCase() == "LI"){
console.log("aaa");
}
}
for(var i=0; i<5; i++){
// 创建一个li节点
var newLi = document.createElement("li");
// 为li节点赋值
newLi.innerHTML = i+6;
// 把节点插入ul
oul.appendChild(newLi);
}
}
</script>
</head>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
</body>
</html>
事件的默认行为:
当一个事件发生的时候浏览器自己默认做的事情
event.preventDefault();//全支持
window.event.returnValue = false;//该特性已经从 Web 标准中删除,虽然一些浏览器目前仍然支持它,但也许会在未来的某个时间停止支持,请尽量不要使用该特性。
return false;//不建议滥用,jq中可以同时阻止冒泡和默认事件。return false等效于同时调用e.preventDefault()和e.stopPropagation()
stopDefault(event); // 兼容
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function(){
var oLink = document.getElementsByTagName("a")[0];
var oForm = document.getElementsByTagName("form")[0];
var aInput = document.getElementsByTagName("input");
oLink.onclick = function(e){
var evt = e || event;
console.log("aaa");
evt.preventDefault();
// return false;
}
}
</script>
</head>
<body>
<a href="">test</a>
<form action="">
<input type="text">
<input type="submit" value="提交">
</form>
</body>
</html>
addEventListener() 方法
addEventListener() 方法用于向指定元素添加事件句柄。
提示: 使用 removeEventListener() 方法来移除 addEventListener() 方法添加的事件句柄。
该方法一共三个参数element.addEventListener(event, function, useCapture)
参数1:event 必须。字符串,指定事件名。注意: 不要使用 “on” 前缀。 例如,使用 “click” ,而不是使用 “onclick”。
参数2:function 必须。指定要事件触发时执行的函数。当事件对象会作为第一个参数传入函数。 事件对象的类型取决于特定的事件。例如, “click” 事件属于 MouseEvent(鼠标事件) 对象。
参数3:useCapture 可选。布尔值,指定事件是否在捕获或冒泡阶段执行。true 事件句柄在捕获阶段执行。false 默认。事件句柄在冒泡阶段执行
您可以在文档中添加许多事件,添加的事件不会覆盖已存在的事件。如果使用普通的点击事件,后面绑定的会覆盖前面的。
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#outer{
width: 200px;
height: 200px;
background-color: red;
}
#inner{
width: 100px;
height: 100px;
background-color: blue;
}
</style>
<script>
window.onload = function(){
var outer = document.getElementById("outer");
var inner = document.getElementById("inner");
/*
如果使用简单的定义事件,则后面定义的会覆盖前面的
比如:
outer.onclick = function(){
alert("函数1");
}
outer.onclick = function(){
alert("函数2");
}
则后面定义的会覆盖前面一个,点击会输出函数2。
如果想清空点击事件,则只需要令: outer.onclick = null;
*/
// 对于通过DOM二级方法绑定的事件,后面绑定的不会覆盖前面的,可以添加许多事件,添加的事件不会覆盖已存在的事件
outer.addEventListener("click",foo);
outer.addEventListener("click",bar);
inner.addEventListener("click",baz);
function baz(){
console.log("inner");
}
function foo(){
console.log("outer1");
}
function bar(){
console.log('outer2');
}
// 但是通过DOM二级绑定的方法,如果想清空事件就要使用removeEventListener("click",foo)和removeEventListener("click",bar);
// 因为ie不支持addEcentListener,所以我们封装一个兼容函数
function addEvent(obj, type, fun){
if(obj.addEventListener){
obj.addEventListener(type,fun,false);
}else{
obj.attachEvent("on"+type,fun);
}
}
function removeEvent(obj, type, fun){
if(obj.removeEventListener){
obj.removeEventListener(type,fun,false);
}else{
obj.detachEvent("on"+type,fun);
}
}
function test() {
alert("test");
}
// 通过封装函数来绑定一个事件
addEvent(outer, "click", test)
}
</script>
</head>
<body>
<div id="outer">
<div id="inner">
</div>
</div>
</body>
obj.detachEvent("on"+type,fun);
}
}
function test() {
alert("test");
}
// 通过封装函数来绑定一个事件
addEvent(outer, "click", test)
}
</script>
</head>
<body>
<div id="outer">
<div id="inner">
</div>
</div>
</body>
</html>