1. js代码书写位置&事件初识&文档加载
-
js书写位置共四种,下面先来看前三种:
- 第一种方式:head中使用script标签,令type属性为"text/javascript",不写type默认也是"text/javascript"
- 第二种方式:将js代码写到标签的属性中,如onlick属性,当我们点击按钮时,js代码才会执行
- 第三种方式:head中使用script标签,指明src引入一个外部的js文件
-
在讲解第四种书写位置时,先来看事件和文档加载:
- ps:第一种和第三种方式也可以给js绑定事件,还是上例,如果通过在script标签中使用js代码绑定事件,首先要找到button按钮,然后为他绑定onclick事件,如下代码(下例中,onclik事件后面为function函数,称为回调函数,不由我们调用,当触发onclik事件时,自动调用),最终页面显示效果是:点击提交按钮后,没有反应(未弹出提交成功的弹窗),具体原因文档加载会讲
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
var btn = document.getElementById("btn");
btn.onclick = function(){
alert("提交成功");
};
</script>
</head>
<body>
<button id="btn">
提交
</button>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="btn">
提交
</button>
<script>
var btn = document.getElementById("btn");
btn.onclick = function(){
alert("提交成功");
};
</script>
</body>
</html>
2. 再会js中的事件
-
js语言本身不会产生事件,产生事件的是网页文档和网页文档中的html元素。事件就是网页文档或网页元素对外发出的通知。 -
html事件发生在html元素上,如上例中button按钮的onclick。html事件可以是浏览器行为,也可以是用户行为,如下html事件的实例:
- html页面完成加载(浏览器行为)
- html input字段改变时(浏览器行为)
- html按钮被点击(用户行为)
-
通常,当事件发生时,可以触发js代码。如果js需要对DOM对象触发的事件进行处理,就需要监听事件,浏览器会自动调用监听事件的js函数,js监听事件的方式有三种:
- 内联属性监听:
<button id="btn" onclick="alert('提交成功')">提交</button> (已接触) - DOM属性绑定监听:即上例
btn.onclick=function(){xxx} (已接触) - 使用事件监听函数:对HTML元素对象调用
addEventListener(event,function,useCapture) 方法或attachEvent() 方法,绑定事件的处理函数(后续讲解) -
常见的html事件如下:(各种事件可以在后续学习中慢慢体会,下表仅是部分事件)
事件 | 描述 |
---|
onchange | html元素改变 | onclick | 用户点击html元素 | onmousemove | 鼠标在元素中移动时发生 | onmouseover | 鼠标指针移动到指定的元素上时发生 | onmousedown | 当鼠标在元素上按下时发生 | onmouseup | 当鼠标按键在元素上松开时发生 | onmouseout | 用户从一个html元素上移开鼠标时发生 | onkeydown | 用户按下键盘按键 | onload | 浏览器已完成页面的加载 |
- onload是浏览器完成页面加载后自动触发,因此上例中的问题,除了使用js第四种书写位置,还可以通过在head的script标签中为元素绑定onload事件解决
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function(){
var btn = document.getElementById("btn");
btn.onclick = function(){
alert("hello");
};
};
</script>
</head>
<body>
<button id="btn">提交</button>
</body>
</html>
3. 深入理解事件
- 关于事件,在前面章节我们已经有了初步的接触,事件指的就是用户与浏览器交互的一瞬间。我们通过为指定事件绑定回调函数的形式来处理事件,当指定事件触发以后,我们的回调函数就会被调用,这样我们的页面就可以完成和用户的交互了。
3.1 事件触发和事件对象
- 事件触发:
- 事件的发生(触发)主要是由用户操作引起的。
- 如mousemove这个事件就是由于用户移动鼠标引起的,在鼠标指针移动的过程中该事件会持续发生
- 当指定事件被触发时,浏览器就会调用对应的函数(代码)去响应事件。一般情况下,事件每触发一次,函数就会执行一次。因此,设置鼠标移动的事件可能会影响到鼠标的移动速度,所以设置该类事件时一定要谨慎。
- 事件对象:
- 当事件被触发时,就会调用响应函数,在DOM标准的浏览器中,浏览器每次都会将一个事件对象作为实参传递进响应函数。在事件对象中封装了当前事件相关的一切信息,比如鼠标的坐标,键盘哪个按键被按下,鼠标滚轮滚动的方向等等。
- IE中的事件对象:
- IE8以上的浏览器和标准浏览器一样
- 在IE8及以下的浏览器中,响应函数被触发时,浏览器不会传递事件对象,而是将事件对象作为window对象的属性保存。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style type="text/css">
#areaDiv {
border: 1px solid black;
width: 300px;
height: 50px;
margin-bottom: 10px;
}
#showMsg {
border: 1px solid black;
width: 300px;
height: 20px;
}
</style>
<script>
window.onload = function(){
var areaDiv = document.getElementById("areaDiv");
var showMsg = document.getElementById("showMsg");
areaDiv.onmousemove = function(event){
event = event || window.event;
var x = event.clientX;
var y = event.clientY;
showMsg.innerHTML = "x = "+x + " , y = "+y;
};
};
</script>
</head>
<body>
<div id="areaDiv"></div>
<div id="showMsg"></div>
</body>
</html>
- 事件对象event包含与创建它的特定事件有关的属性和方法,触发的事件类型不一样,可用的属性和方法也不一样。下图第一张图片为标准浏览器一些公共方法或属性,第二张图片为IE8及以下浏览器一些公共方法或属性。
-
下述案例为让id为box1的div跟随鼠标移动而移动:
- 设置body的width和height为一个相对较大的值,可以出现水平和垂直方向滚动条
- 设置box1开启绝对定位
- 对于浏览器滚动条,chrome认为浏览器滚动条是body元素的,可以通过
document.body.scrollTop 来获取;火狐等浏览器认为滚动条是html的,通过document.documentElement.srollLeft 获取 clientX 和clientY 用于获取onmousemove事件中鼠标在当前的可见窗口的坐标pageX 和pageY 用于获取onmousemove事件中鼠标在当前页面的坐标,但是IE8及以下浏览器不兼容。- box1绝对定位的偏移量为可见窗口坐标加上滚动条偏移量
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
#box1{
width: 100px;
height: 100px;
background-color: red;
position: absolute;
}
</style>
<script type="text/javascript">
window.onload = function(){
var box1 = document.getElementById("box1");
document.onmousemove = function(event){
var st = document.body.scrollTop || document.documentElement.scrollTop;
var sl = document.body.scrollLeft || document.documentElement.scrollLeft;
event = event || window.event;
var left = event.clientX;
var top = event.clientY;
box1.style.left = left + sl + "px";
box1.style.top = top + st + "px";
};
};
</script>
</head>
<body style="height: 1000px;width: 2000px;">
<div id="box1"></div>
</body>
</html>
3.2 事件的绑定(事件监控)
-
在第三章中,我们已经提到了事件绑定的三种方式:
- 方式一:内联属性监听,也可以称为通过HTML元素指定事件属性来绑定
- 方式二:DOM属性绑定监听:通过DOM对象指定的属性来绑定
- 方式三:设置事件监听器(事件监听函数),使用
元素对象.addEventListener() 或者元素对象.attachEvent() 方法。 -
前两种事件绑定方式的比较
-
方式一:举例<button onclick="alert('hello');alert('world');">按钮</button> ,这种方式,当我们点击按钮以后,onclik属性中的js代码将会依次执行,也就是点击按钮后,页面会弹出两个提示框。除了直接将代码编写到onclik属性中,也可以事先在外部定义好函数。
- 优点:设定步骤非常简单,并且能够确保事件处理程序在载入时被设定。
- 缺点:将js和html代码编写到一起,并不推荐;只能同时为一个元素的一个事件绑定一个响应函数,不能绑定多个,如果绑定了多个,则后边会覆盖掉前边的(在方式二讲解)
-
方式二:举例如下,效果同方式一。 var btn = document.getElementById("btn");
btn.onclik = function(){
alert("hello");
alert("world");
}
- 优点:html代码和js代码写在不同位置,维护起来更加容易。
- 缺点:只能同时为一个元素的一个事件绑定一个响应函数,不能绑定多个,如果绑定了多个,则后边会覆盖掉前边的。如下例,同一个btn元素的onclick事件绑定了两个响应函数,则第二个会覆盖第一个,即结果只有一个提示框,内容为"hello javascript"("hello"和"world"提示框内容不会生效)
var btn = document.getElementById("btn");
btn.onclik = function(){
alert("hello");
alert("world");
}
btn.onclick = function(){
alert("hello javascript");
}
-
方式一和方式二我们在前述章节都有所接触,这两种方式都是日常用的比较多的,但更推荐使用第二种方式。两种方式都存在一个缺点:只能同时为一个元素的一个事件绑定一个响应函数,不能绑定多个,可以使用方式三来解决这个问题。 -
方式三:设置事件监听器详解:
- IE8以上浏览器及其他非IE浏览器:使用
元素.addEventListner(参数1, 参数2, 参数3) 可以同时为一个元素的相同事件同时绑定多个响应函数,当事件被触发时,响应函数将会按照函数的绑定顺序执行。该方法不支持IE8及以下的浏览器
- 参数1:事件的字符串,去掉on,如onclik事件需要传"click"
- 参数2:回调函数,当事件触发时调用该函数
- 参数3:boolean,是否在捕获阶段触发事件,一般传false。事件捕获阶段含义在事件的传播一章中详细解释,暂且认为就是加载时。
- IE8及以下浏览器:使用
元素.attachEvent(参数1, 参数2) ,也可以为一个元素的相同事件绑定多个响应函数,但是执行顺序与addEventListener 相反,即先绑定的后执行,后绑定的先执行。
- 参数1:事件的字符串,要on,同
addEventListener - 参数2:回调函数,当事件触发时调用该函数
- this补充:我们知道函数都有一个隐含参数this,函数的不同使用方式this的含义不同,在事件监听函数(事件处理程序)中
- IE8及以下浏览器,this是window
- 其他浏览器的this就是设置了该事件处理程序的元素(从另一个角度想,
元素.事件监听函数() 本质是以方法的形式调用,故this是调用方法的那个对象,也即前面的元素) <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function(){
var btn01 = document.getElementById("btn01");
var btn02 = document.getElementById("btn02");
var btn03 = document.getElementById("btn03");
var bind = function(obj, eventStr, callback){
if(obj.addEventListener){
obj.addEventListener(eventStr, callback, false);
}
else{
obj.attachEvent("on" + eventStr, callback);
}
}
bind(btn03, "click", function(){
alert(this);
})
}
</script>
</head>
<body>
<button id="btn01">IE8及以下浏览器</button>
<br><br>
<button id="btn02">其他浏览器</button>
<br><br>
<button id="btn03">兼容模式</button>
</body>
</html>
3.3 事件的冒泡
- 事件的冒泡(Bubble):
- 指事件的向上传导,当后代元素上的事件被触发时,其祖先元素相同事件也会被触发。其本质是向上一层(上一代)传导,如下例中id分别为box1、box2、box3的div元素存在爷爷–爸爸–儿子的关系,此外,body是box1的爸爸,四者都绑定了单击响应函数,当触发box3的onclik事件,向上传导至box2,即触发box2的单击响应函数,box2又向上传导至box1,以此类推。
- 以onclik事件为例,由于子元素是父元素(祖先元素)的一部分,故单击子元素,其本质也是单击父元素(祖先元素),从这个角度来看,父元素(祖先元素)的onclik事件必然会触发,当然,我们正好单击了子元素,子元素本身的onclik事件也会触发。
- 在开发中,大部分情况冒泡都是有用的,如果不希望发生事件冒泡(单击子元素就是单击子元素本身,不认为单击了父元素),可以通过事件对象来取消冒泡:设置
event.cancelBubble=true 取消。还是下例当我们设置box3的event.cancelBubble=true 时,单击box3只会触发box3的onclik事件,由于取消冒泡,不会传导至box2,box2也因此无法继续传导下去;但是,直接单击box2,依然会触发box1、body的onclik事件。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
#box1{
background-color: yellow;
width: 300px;
height: 300px;
}
#box2{
background-color: #bfa;
width: 200px;
height: 200px;
}
#box3{
background-color: gray;
width: 100px;
height: 100px;
}
</style>
<script type="text/javascript">
window.onload = function(){
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
var box3 = document.getElementById("box3");
box3.onclick = function(event){
alert("我是box3的单击响应函数");
};
box2.onclick = function(event){
alert("我是box2的单击响应函数");
};
box1.onclick = function(event){
alert("我是box1的单击响应函数");
}
document.body.onclick = function(){
alert("我是body的单击响应函数");
};
};
</script>
</head>
<body>
<div id="box1">
<div id="box2">
<div id="box3"></div>
</div>
</div>
</body>
</html>
- 下述案例为让id为box1的div跟随鼠标移动而移动,但是不会作用于box2(基于上一小节的案例)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
#box1{
width: 100px;
height: 100px;
background-color: red;
position: absolute;
}
</style>
<script type="text/javascript">
window.onload = function(){
var box2 = document.getElementById("box2");
box2.onmousemove = function(event){
event = event || window.event;
event.cancelBubble = true;
};
var box1 = document.getElementById("box1");
document.onmousemove = function(event){
var st = document.body.scrollTop || document.documentElement.scrollTop;
var sl = document.body.scrollLeft || document.documentElement.scrollLeft;
event = event || window.event;
var left = event.clientX;
var top = event.clientY;
box1.style.left = left + sl + "px";
box1.style.top = top + st + "px";
};
};
</script>
</head>
<body style="height: 1000px;width: 2000px;">
<div id="box2" style="width: 500px; height: 500px; background-color: #bfa;"></div>
<div id="box1"></div>
</body>
</html>
3.4 事件的委派
- 在讲解事件的委派前,先来看一个例子(场景):ul祖先元素下有四个li子元素,其中第2-4个li元素均有一个a子元素,分别称作超链接一、超链接二、超链接三,三个a元素的class均为link。我们想要为三个a元素均绑定单击响应函数,可以使用循环遍历每个a并绑定单击响应函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function(){
var links = document.getElementsByClassName("link");
for (var i=0; i < links.length; i++){
links[i].onclick = function(event){
alert("我是超链接的单击响应函数");
}
}
}
</script>
</head>
<body>
<ul id="ul" style="background-color: #bfa;">
<li>
<p>p元素</p>
</li>
<li>
<a href="javascript:;" class="link">超链接一</a>
</li>
<li>
<a href="javascript:;" class="link">超链接二</a>
</li>
<li>
<a href="javascript:;" class="link">超链接三</a>
</li>
</ul>
</body>
</html>
- 上述代码通过for循环的方式,虽然也完成了我们的需求:为每个超链接绑定单击响应函数,但是仍存在以下问题:
- for循环的方式,进行了3次事件绑定操作,会影响程序的性能
- 假如有一个button按钮,点击后会新增一个超链接,我们希望新增的超链接也绑定同样的单击响应事件,上述代码无法完成(只能完成已有超链接的单击响应事件)
- 解决思路:只绑定一次事件,即可应用到多个元素上,即使元素是后添加的
- 解决方案:事件的委派:
- 指将事件统一绑定给元素(暂且称为目的子元素)共同的祖先元素上,通过祖先元素的event判断是否为目的子元素,如果是,则执行相应的代码。
event.target :表示触发事件的对象,以onclik为例,假如我们单击的是子元素,则返回子元素对象,假如我们单击的是子元素以外的父元素部分,则返回父元素对象。 - 事件的委派本质是为祖先元素绑定事件,但最终效果是为子元素绑定了事件
- 事件委派是利用了冒泡,当后代元素事件触发时,会一直冒泡到祖先元素,从而通过祖先元素的相应函数来处理事件。
- 通过委派可以减少事件绑定次数,提高了程序性能;还能为新增元素绑定事件,解决了上述问题。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function(){
var btn = document.getElementById("btn01");
btn.onclick = function(){
var liLable = document.createElement("li");
liLable.innerHTML = "<a href='javascript:;' class='link'>新增超链接</a>"
var ulLable = document.getElementById("ul");
ulLable.appendChild(liLable);
}
var ulLable = document.getElementById("ul");
ulLable.onclick = function(event){
event = event || window.event;
if (event.target.className == "link"){
alert("触发单击响应函数");
}
}
}
</script>
</head>
<body>
<button id="btn01">添加超链接</button>
<ul id="ul" style="background-color: #bfa;">
<li>
<p>p元素</p>
</li>
<li>
<a href="javascript:;" class="link">超链接一</a>
</li>
<li>
<a href="javascript:;" class="link">超链接二</a>
</li>
<li>
<a href="javascript:;" class="link">超链接三</a>
</li>
</ul>
</body>
</html>
3.5 事件的传播
- 在网页中标签与标签之间是有嵌套关系的,比如下图,如果这时用户点击了sample按钮,则会以该按钮作为事件目标触发一次点击事件。事件从触发到完成这个过程称为事件传播。
<html>
<body>
<div>
<button id="bar">sample</button>
</div>
</body>
</html>
- 关于事件传播微团公司和网景公司有不同的理解,W3C则综合了两家公司的方案:
- 微团公司:事件应该由外向内传播,也就是当事件触发时,应该先触发当前元素事件,然后再向当前元素的祖先元素上传播,也就是说事件应该在冒泡阶段执行
- 网景公司:事件应该是由外向内传播的,也就是当前事件触发时,应该先触发当前元素的最外层的祖先元素,然后再向内传播给后代元素
- W3C:综合了两家公司方案,将事件传播分成三个阶段:
- 捕获阶段:这一阶段会从window对象开始向下一直遍历到目标对象,如果发现有对象绑定了响应事件则做相应的处理(从最外层的祖先元素,向目标元素进行事件捕获,但默认此时不会触发事件)
- 目标阶段:这一阶段已经遍历结束,事件捕获到目标元素,执行目标对象上绑定的响应函数。
- 事件冒泡阶段:这一阶段,事件的传播方式和捕获正好相反,会从事件目标一直向上遍历,直到window对象结束,这时对象上绑定的响应函数也会执行。
- 在事件的绑定一节,函数
addEventListener() 第三个参数为boolean,如果为true则表示在捕获阶段触发事件,一般我们并不希望这样,因此多数情况为false,该参数默认值为false,因此也可以省略不写。实际上,将参数值设为true后,最终的表现结果和false是一样的,由于捕获阶段下一步就是目标阶段,这个过程在后台进行,从前端结果来看,并无区别。 - IE8及以下浏览器中没有捕获阶段
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
#box1{
width: 300px;
height: 300px;
background-color: yellowgreen;
}
#box2{
width: 200px;
height: 200px;
background-color: yellow;
}
#box3{
width: 150px;
height: 150px;
background-color: skyblue;
}
</style>
<script type="text/javascript">
window.onload = function(){
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
var box3 = document.getElementById("box3");
bind(box1,"click",function(){
alert("我是box1的响应函数")
});
bind(box2,"click",function(){
alert("我是box2的响应函数")
});
bind(box3,"click",function(){
alert("我是box3的响应函数")
});
};
function bind(obj , eventStr , callback){
if(obj.addEventListener){
obj.addEventListener(eventStr , callback , true);
}else{
obj.attachEvent("on"+eventStr , function(){
callback.call(obj);
});
}
}
</script>
</head>
<body>
<div id="box1">
<div id="box2">
<div id="box3"></div>
</div>
</div>
</body>
</html>
3.6 事件的取消
- 在讲解事件取消前,我们先来看下例:
- 例子:
box1-->box2-->box3-->a 从左到右辈分逐步降低,其中a 是一个超链接,链接到百度 首页,同时,a绑定了三个单击响应函数:第一个单击响应函数效果是出现弹窗,内容a1;第二个单击响应函数效果是出现弹窗,内容a2;第三个单击响应函数效果是出现弹窗,内容a3。box1、box2、box3也均绑定了单击响应函数,效果都是出现弹窗,内容分别为"我是box1的单击响应函数"、“我是box2的单击响应函数”、“我是box3的单击响应函数”。 - 动作:浏览器打开网页,鼠标单击"百度超链接"
- 效果:
- 首先连续出现6个弹窗,弹窗内容为:a1、a2、a3、我是box3的单击响应函数、我是box2的单击响应函数、我是box1的单击响应函数
- 然后新打开一个网页,跳转至百度首页
- 解释:单击"百度超链接",也就是会触发标签a绑定的事件,依次弹出弹窗a1、a2、a3;在事件传播的冒泡阶段,依次触发box3、box2、box1的单击响应函数,故依次出现弹窗"我是box3的单击响应函数"、“我是box2的单击响应函数”、“我是box1的单击响应函数”。超链接a标签本身有默认行为:链接到其他网页并打开,故浏览器打开一个新的网页跳转至百度首页。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function(){
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
var box3 = document.getElementById("box3");
var link = document.getElementById("link");
if (link.addEventListener){
link.addEventListener("click", function(){
alert("a1");
})
}
else{
link.attachEvent("onclick", function(){
alert("a3");
})
}
if (link.addEventListener){
link.addEventListener("click", function(){
alert("a2");
})
}
else{
link.attachEvent("onclick", function(){
alert("a2");
})
}
if (link.addEventListener){
link.addEventListener("click", function(){
alert("a3");
})
}
else{
link.attachEvent("onclick", function(){
alert("a1");
})
}
function boxFun(obj, content){
obj.onclick = function(){
alert(content);
}
}
boxFun(box3, "我是box3的单击响应函数");
boxFun(box2, "我是box2的单击响应函数");
boxFun(box1, "我是box1的单击响应函数")
}
</script>
</head>
<body>
<div id="box1">
box1
<div id="box2">
box2
<div id="box3">
box3
<br>
<a href="http://www.baidu.com" target="_blank" id="link">百度超链接</a>
</div>
</div>
</div>
</body>
</html>
- 在上例效果的解释中,其实包含了两大方面:一是事件传播;二是默认行为。因此事件取消也是从这两方面就行阐述。
3.6.1 取消事件传播
-
在事件的冒泡一章中,我们提到,可以用event.cancelBubble=true 来取消冒泡,和event.stopPropagation() 有异曲同工之妙。 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function(){
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
var box3 = document.getElementById("box3");
var link = document.getElementById("link");
if (link.addEventListener){
link.addEventListener("click", function(){
alert("a1");
})
}
else{
link.attachEvent("onclick", function(){
alert("a3");
})
}
if (link.addEventListener){
link.addEventListener("click", function(event){
alert("a2");
event.cancelBubble = true;
})
}
else{
link.attachEvent("onclick", function(event){
alert("a2");
event.cancelBubble = true;
})
}
if (link.addEventListener){
link.addEventListener("click", function(){
alert("a3");
})
}
else{
link.attachEvent("onclick", function(){
alert("a1");
})
}
function boxFun(obj, content){
obj.onclick = function(){
alert(content);
}
}
boxFun(box3, "我是box3的单击响应函数");
boxFun(box2, "我是box2的单击响应函数");
boxFun(box1, "我是box1的单击响应函数")
}
</script>
</head>
<body>
<div id="box1">
box1
<div id="box2">
box2
<div id="box3">
box3
<br>
<a href="http://www.baidu.com" target="_blank" id="link">百度超链接</a>
</div>
</div>
</div>
</body>
</html>
3.6.2 取消默认行为
-
默认行为:具体指浏览器对当前事件的默认行为,比如上例,浏览器对当前超链接a标签的onclik事件具有默认的网页跳转行为(触发完成超链接的onclick事件后,浏览器自动默认执行跳转操作)。类似地,用户点击注册,浏览器自动跳转至注册成功页;用户点击提交按钮后提交成功等等 -
取消默认行为:对于超链接默认行为加以取消,如取消点击超链接后的跳转,注册信息填写有误时,点击注册不会跳转至注册成功页,提交信息有误时,无法提交成功。 -
取消默认行为有两种方法:
- 方法一:在事件响应函数中使用
event.preventDefault() ,还是本章开头的案例,在link的第二个onclik事件响应函数中,添加event.preventDefault() 代码,最终效果是出现6个弹窗,但网页不会跳转。也就是说浏览器对事件的默认行为是发生在事件传播之后的,无论在link的第几个onclik事件响应函数中添加event.preventDefault() ,都不会阻止事件传播,但会取消默认的跳转行为。在IE8及以下浏览器通过event.returnValue=false 方式实现。 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function(){
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
var box3 = document.getElementById("box3");
var link = document.getElementById("link");
if (link.addEventListener){
link.addEventListener("click", function(){
alert("a1");
})
}
else{
link.attachEvent("onclick", function(){
alert("a3");
})
}
if (link.addEventListener){
link.addEventListener("click", function(event){
alert("a2");
event.preventDefault();
})
}
else{
link.attachEvent("onclick", function(event){
alert("a2");
event.returnValue=false;
})
}
if (link.addEventListener){
link.addEventListener("click", function(){
alert("a3");
})
}
else{
link.attachEvent("onclick", function(){
alert("a1");
})
}
function boxFun(obj, content){
obj.onclick = function(){
alert(content);
}
}
boxFun(box3, "我是box3的单击响应函数");
boxFun(box2, "我是box2的单击响应函数");
boxFun(box1, "我是box1的单击响应函数")
}
</script>
</head>
<body>
<div id="box1">
box1
<div id="box2">
box2
<div id="box3">
box3
<br>
<a href="http://www.baidu.com" target="_blank" id="link">百度超链接</a>
</div>
</div>
</div>
</body>
</html>
-
方式二:在事件的响应函数中return false ,这种方法只适用于通过属性注册的处理程序,也就是说只适用于第一种和第二种事件绑定方式,第三种方法不适用。其他未特别说明,则表示都适用。 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function(){
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
var box3 = document.getElementById("box3");
var link = document.getElementById("link");
function boxFun(obj, content){
obj.onclick = function(){
alert(content);
}
}
boxFun(box3, "我是box3的单击响应函数");
boxFun(box2, "我是box2的单击响应函数");
boxFun(box1, "我是box1的单击响应函数")
}
</script>
</head>
<body>
<div id="box1">
box1
<div id="box2">
box2
<div id="box3">
box3
<br>
<a href="http://www.baidu.com" target="_blank" id="link" onclick="alert('a'); return false;">百度超链接</a>
</div>
</div>
</div>
</body>
</html>
|