4.1.4 事件冒泡
1 什么是冒泡
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> </style> </head> <body> <div id="content"> 外层元素 <span>内层元素</span> 外层元素 </div> <div id="msg"></div> <script src="jQuery环境/jquery-1.12.4.js"></script> <script> $(function(){ $("span").bind("click",function(){ var txt = $("#msg").html()+"<P>内层div元素被单击</p>"; $("#msg").html(txt); }); $("#content").bind("click",function(){ var txt = $("#msg").html()+"<P>外层div元素被单击</p>"; $("#msg").html(txt); }) }) </script> </body> </html>
创建一个 body > div > span 的 HTML 结构
给span绑定一个 click 函数,点击span元素,会依次弹出3个元素,span > div > body
2 事件冒泡引发的问题
当点击 <span> 时只需要触发 <span> 元素事件,而不触发 div 和 body 事件。
解决方法:
♠ 事件对象
在程序中使用事件对象非常简单,只需添加一个参数
$("element").bind("click",function(event){ //event :事件对象 })
单击“event”元素时,事件对象就被创建,这个事件对象只有事件处理函数可以访问,事件处理函数执行完毕后,事件对象被销毁。
♠ 停止事件冒泡
停止事件冒泡可以阻止事件中其他对象的事件处理函数被执行,stopPropagation() 方法来停止事件冒泡
$("span").bind("click",function(){ var txt = $("#msg").html() + "<p>内层span元素被单机.</p>"; $("#msg").html(txt); event.stopPropagation(); //停止事件冒泡 });
♠ 阻止默认行为
网页元素有默认行为:单击超链接,提交表单等,有时候需要阻止元素默认行为。 event.preventDefault() 有时候等价于 return false ;
<body> <div id="content"> 外层元素 <span>内层元素</span> 外层元素 </div> <a href="http://www.baidu.com" class="aaa">aaa</a> <div id="msg"></div> <script src="jQuery环境/jquery-1.12.4.js"></script> <script> $(function(){ $(".aaa").bind("click",function(event){ event.preventDefault();
//return false;
// event.preventDefault() 等价于 return false; 同样的效果
}); }) </script> </body>
♠ 事件捕获
事件捕获和事件冒泡刚好相反,并且 JQ 不支持事件捕获,需要直接使用原生 JS 。
4.1.5 事件对象的属性
jQ 对时间对象的常用属性进行了封装,使得事件处理在各大浏览器下都可以正常运行而不需要进行浏览器类型拍段
(1)event.type() 方法
该方法作用是可以获取到事件的类型
<script> $("a").click(function(event){ alert(event.type); //获取事件类型 event.type 后面不加(); return false //阻止链接跳转 }) </script>
(2)event.preventDefault() 方法 阻止默认事件行为。
(3)event.stopProgation() 方法 阻止事件的冒泡
(4)event.target() 方法
获取到触发事件的元素
(5)event.relatedTarget() 方法
在执行标准的 DOM 中,mouseover 和 mouseout 所发生的元素可以通过 event.target() 方法来访问,相关元素是通过 event.relatedTarget() 方法访问的,event.relatedTarget() 方法在 mouseover 中相当于IE中的 event.fromElement() 方法,在mouseout 中相于IE 中的 event.toElement 方
(6)event.pageX () 方法 / enent.pageY() 方法
获取到光标相对于X坐标和Y坐标,不使用 JQ 的 IE 浏览器使用 event.x() 和 event.y() 方法。FF浏览器使用 event.pageX() / event.pageY() .如果页面有滚动条的话,还要加上滚动条宽度或高度,在IE中应减去默认的2PX 边框
(7)event.which() 方法
在鼠标单击事件中获取到鼠标的左/中/右 键,在键盘事件中获取键盘按键
$(function(){ $("body").mousedown(function(e){ alert(e.which) }) })
1 = 左键, 2 = 中键, 3 = 右键
4.1.6 移除事件
可以为同一个元素绑定多个事件,也可以为多个元素绑定同一个事件。假设网页上有一个 <button> 元素,为其绑定多个事件
<body> <button id="btn">点击我</button> <div id="test"></div> <button id="delTwo">删除第二个元素</button> <script type="text/javascript"> $(function(){ $("#btn").bind("click",function(){ $("#test").append("<p>我的绑定函数1</p>"); }).bind("click",function(){ $("#test").append("<p>我的绑定函数2</p>"); }); }) </script> </body>
点击会有2个绑定函数出现
① 移除按钮元素上以前注册的事件
首先在网页上添加一个移除事件按钮
<button id="delAll">删除所有事件</button>
绑定一个事件
$("#delAll").click(function(){ //处理函数 });
编写处理函数,用于删除所有click事件
$("#delAll").click(function(){ $("#btn").unbind("click"); });
unbind() 方法的语法结构:
unbind([type][,data]);
第一个参数是事件类型,第二个参数是将要移除的函数
(1)如果没有参数则移除所有绑定事件
(2)如果提供了事件类型作为参数,则只删除该类型事件
(3)如果把在绑定时传递的处理函数作为第二个参数,则只有这个特定事件处理函数被删除。
② 移除<button>元素的其中一个事件
首先需要为这些匿名处理函数指定一个变量
<script type="text/javascript"> $(function(){ $("#btn").bind("click",myFun1 = function(){ $("#test").append("<p>我的绑定函数1</p>"); }).bind("click",myFun2 = function(){ $("#test").append("<p>我的绑定函数2</p>"); }); }) </script>
单独删除某一个变量
$("#delTwo").click(function(){ $("#btn").unbind("click",muFun2); //删除“绑定函数2” })
完整代码:
<body> <button id="btn">点击我</button> <div id="test"></div> <button id="delTwo">删除第二个元素</button> <script type="text/javascript"> $(function(){ $("#btn").bind("click",myFun1 = function(){ $("#test").append("<p>我的绑定函数1</p>"); }).bind("click",myFun2 = function(){ $("#test").append("<p>我的绑定函数2</p>"); }); }) $("#delTwo").click(function(){ $("#btn").unbind("click",myFun2); //删除“绑定函数2” }) </script> </body>
效果:
点击删除第二个元素按钮之后再点击“点击我” ,则只出现一个绑定事件
话外篇
对于只需要触发一次,随后就要立即解除绑定的情况,jQuery 提供了一种 one() 方法。可以为元素绑定处理函数,当函数被触发一次后,立即被删除(既在每个对象上,事件处理函数只会被执行一次)
使用结构和方法与 bind() 类似。
one(type,[data],fn);
<body> <button id="btn">点击我</button> <div id="test"></div> <script type="text/javascript"> $(function(){ $("#btn").one("click",function(){ $("#test").append("<p>我的绑定函数1</p>"); }).one("click",function(){ $("#test").append("<p>我的绑定函数2</p>"); }).one("click",function(){ $("#test").append("<p>我的绑定函数</p>"); }); }) </script> </body>
点击按钮只能点击一次,再点击就失效了。
4.1.7 模拟操作
1 常用模拟
一般事件是需要用户点击按钮,才能触发click事件,有时候,需要通过模拟用户操作,来打到单击效果,例如,当用户进入页面后,就触发 click 事件,而不需要用户去主动单击
在jQuery中,可以使用 trigger() 方法完成模拟操作
$("#btn").trigger("click");
页面加载后会立即输出结果。
$("#btn").trigger("click") // 等价于 $("#btn").click();
2 触发自定义事件
trigger() 不仅能触发浏览器支持的具有相同名称的事件,也可以触发自定义名称事件
例如为元素绑定一个 “myClick” 的事件。
$("#btn").trigger("myClick");
连续点击都会触发 myClick 事件:
$(function(){ $("#btn").bind("myClick",function(){ $("#test").append("<p>我的自定义事件</p>") }); $("#btn").bind("click",function(){ $(this).trigger("myClick"); }).trigger("myClick"); })
3 传递参数
trigger(type[,data]) 方法有2个参数,第一个要触发的类型,第二个传递给事件处理函数的附加数据,以数组形式传递。通常可以通过传递一个参数给回调函数来区别这次事件是代码触发还是用户触发。
示例:
4 执行默认操作
trigger() 方法触发事件后,会执行浏览器默认操作
$("input").trigger("focus");
上述代码不仅会触发<input>元素绑定的focus 事件,也会使<input>元素本身得到焦点(这是浏览器默认操作)
如果只想触发绑定的 focus 事件,而不想执行浏览器默认操作,可以使用 triggerHandler() 方法
$("input").triggerHandler("focus");
该方法会触发<input>元素上绑定的特定事件,同时取消浏览器对此事件的默认操作。即文本框只触发绑定的 focus 事件,而不会得到焦点。
4.1.8 其他方法
1 绑定多个事件类型
为元素一次绑定多个事件类型
$(function(){ $("div").bind("mouseover mouseout",function(){ $(this).toggleClass("over"); }); })
当光标滑入 <div> 时,class 切换为 "over" 当光标滑出 <div> 时,class 切换为先前值。
等同于以下代码:
$(function(){ $("div").bind("mouseover",function(){ $(this).toggleClass("over"); }).bind("mouseout",function(){ $(this).toggleClass("over"); }); })
2 添加事件命名空间,便于管理
<body> <div>test.</div> <button >根据命名空间,删除事件</button> <script type="text/javascript"> $(function(){ $("div").bind("click.plugin",function(){ $("body").append("<p>click 事件</p>") }); $("div").bind("mouseover.plugin",function(){ $("body").append("<p>mouseover 事件</p>") }); $("div").bind("dblclick.plugin",function(){ $("body").append("<p>dblclick 事件</p>") }); $("button").click(function(){ $("div").unbind(".plugin"); }) }) </script> </body>
在所绑定的事件类型后面添加命名空间,这样在删除事件时只需要指定命名空间即可。单击 <button> 元素后,“plugin” 的命名空间被删除,而不在"plugin"的命名空间“dblclick”事件依然存在。
而删除多个事件代码也可以写为链式代码
$("div").unbind("click").unbind("mouseover"); //可以实现同样的效果,但是不如命名空间方法简单直接
3 相同事件命名,不同命名空间执行方法
可以为元素绑定相同的事件类型,然后以命名空间的不同按需调用
<body> <div>test.</div> <button >根据命名空间,删除事件</button> <script type="text/javascript"> $(function(){ $("div").bind("click",function(){ $("body").append("<p>click事件</p>"); }); $("div").bind("click.plugin", function(){ $("body").append("<p>click.plugin事件</p>"); }); $("button").click(function() { $("div").trigger("click!"); // 注意click后面的感叹号 }); }) </script> </body>
当单机<div> 元素后,会同时出发 click 和 click.plugin 事件,如果只单机<button> 则只出发 click 事件,注意:trigger("click!") 后面的感叹号!是作用是匹配所有不包含在命名空间中的 click 方法。
如果需要两者都被出发,去掉感叹号即可
$("div").trigger("click");