js 事件详解 冒泡
起因:正常情况下我点击s2时是先弹出我是children,再弹出我是father,但是却出现了先弹出我是father,后弹出我是children的情况,这种情况是在和安卓app交互的h5页面中出现的,本地测试没有问题,但是在安卓打包的内嵌h5页面就出现了问题。简单化的代码先展示出来。
html代码如下
<div id="father" class="ss1">s1
<div id="children" class="ss2">s2
</div>
</div>
事件绑定如下
$('#father').on('click',function (e) {
alert('我是father')
})
$('#children').on('click',function (e) {
alert('我是children')
e.stopPropagation();
})
借此问题,复习了一下js事件,先看一下几个定义
先来看事件注册
// IE以外的其他浏览器
// target :文档节点、document、window 或 XMLHttpRequest。
// type :字符串,事件名称,不含“on”,比如“click”、“mouseover”、“keydown”等。
// listener :实现了 EventListener 接口或者是 JavaScript 中的函数。
// useCapture :是否使用捕捉,一般用 false,事件触发时,会将一个 Event 对象传递给事件处理程序。 target.addEventListener(type,listener,useCapture);//添加
target.removeEventListener(type,listener,useCapture);//删除
// IE浏览器
// target :文档节点、document、window 或 XMLHttpRequest。
// type :字符串,事件名称,含“on”,比如“onclick”、“onmouseover”、“onkeydown”等。
// listener :实现了 EventListener 接口或者是 JavaScript 中的函数。 target.attachEvent(type, listener);//添加
target.detachEvent(type, listener);// 移除
兼容写法
兼容后的方法
var func = function(){};
//例:addEvent(window,"load",func)
function addEvent(elem, type, fn) {
if (elem.attachEvent) {
elem.attachEvent('on' + type, fn);
return;
}
if (elem.addEventListener) {
elem.addEventListener(type, fn, false);
}
} //例:removeEvent(window,"load",func)
function removeEvent(elem, type, fn) {
if (elem.detachEvent) {
elem.detachEvent('on' + type, fn);
return;
}
if (elem.removeEventListener) {
elem.removeEventListener(type, fn, false);
}
}
获取事件对象和事件源(触发事件的元素)
function eventHandler(e){
//获取事件对象
e = e || window.event;//IE和Chrome下是window.event FF下是e
//获取事件源
var target = e.target || e.srcElement;//IE和Chrome下是srcElement FF下是target
}
事件委托
myTable.onclick = function () {
e = e || window.event;
var targetNode = e.target || e.srcElement;
// 测试如果点击的是TR就触发
if (targetNode.nodeName.toLowerCase() === 'tr') {
alert('You clicked a table row!');
}
}
事件函数的解除绑定
和事件的绑定其实是相对应的,如果需要接触事件的绑定,运行对应的函数就可以了。如果是原生JS绑定则对应运行removeEventListener()和detachEvent()。
如果是jQuery的bind()和delegate()绑定,也是存在对应的解绑函数用以清除注册事件,比如unbind()和undelegate()。
看一个代码示例:
var EventUtil = {
//注册
addHandler: function(element, type, handler){
if (element.addEventListener){
element.addEventListener(type, handler, false);
} else if (element.attachEvent){
element.attachEvent("on" + type, handler);
} else {
element["on" + type] = handler;
}
},
//移除注册
removeHandler: function(element, type, handler){
if (element.removeEventListener){
element.removeEventListener(type, handler, false);
} else if (element.detachEvent){
element.detachEvent("on" + type, handler);
} else {
element["on" + type] = null;
}
}
};
再来看看事件流
几个概念
捕获阶段:事件对象通过目标的祖先从传播窗口到目标的父。这个阶段也被称为捕获阶段。
目标阶段:本次活动对象到达事件对象的事件的目标。这个阶段也被称为目标阶段。如果事件类型指示事件不起泡,则在完成此阶段后,事件对象将停止。
冒泡阶段:事件对象通过目标的祖先中传播以相反的顺序,开始与目标的父和与所述结束窗口。这个阶段也被称为冒泡阶段。
默认行为:事件通常由实现作为用户操作的结果分派,以响应任务的完成,或者在异步活动(例如网络请求)期间发信号通知进度。有些事件可以用来控制下一个实现可能采取的行为(或者撤销实现已经采取的行动)。这个类别中的事件被认为是可取消的,他们取消的行为被称为他们的默认行为。
取消事件:可取消的事件对象可以与一个或多个“默认动作”相关联。要取消事件,请调用该preventDefault()
方法。
一个图片
再上个小demo
<ul>
<li>点我试试</li>
</ul>
<div id="s1" class="ss1">s1
<div id="s2" class="ss2">s2</div>
</div>
var ul = document.getElementsByTagName('ul')[0];
var li = document.getElementsByTagName('li')[0];
element.addEventListener(event, function, useCapture)
document.addEventListener('click',function(e){console.log('document clicked')},true);//第三个参数为true使用捕获,false为冒泡,false为默认
ul.addEventListener('click',function(e){console.log('ul clicked')},true);
li.addEventListener('click',function(e){console.log('li clicked')},true);
//IE低版本兼容写法
li.attachEvent('onclick',function(event){
debugger
console.log('li clicked');
event.cancelBubble=true;
}); s1.addEventListener('click',function () {
console.log('s1 捕获方式')
},true)
s1.addEventListener('click',function () {
console.log('s1 冒泡方式')
},false)
s2.addEventListener('click',function (e) {
console.log('s2 捕获方式')
// e.stopPropagation();
},true)
s2.addEventListener('click',function () {
console.log('s2 冒泡方式')
},false)
点击li时,打印 依次为
1
|
ul clicked li clicked |
点击s1时,打印依次为
s1 捕获方式 s1 冒泡方式
点击s2时,打印依次为
s1 捕获方式 s2 捕获方式 s2 冒泡方式 s1 冒泡方式
处理事件冒泡和默认事件
1、e.preventDefault()
var a = document.getElementById("testA");
a.onclick =function(e){
if(e.preventDefault){
e.preventDefault();//
}else{
window.event.returnValue = false;//IE
//注意:这个地方是无法用return false代替的
//return false只能取消元素
}
}
2、return false javascript的return false只会阻止默认行为,而是用jQuery的话则既阻止默认行为又防止对象冒泡。
//原生js,只会阻止默认行为,不会停止冒泡
var a = document.getElementById("testA");
a.onclick = function(){
return false;//当然 也阻止了事件本身
};
//既然return false 和 e.preventDefault()都是一样的效果,那它们有区别吗?当然有。
//仅仅是在HTML事件属性 和 DOM0级事件处理方法中 才能通过返回 return false 的形式组织事件宿主的默认行为。
1 //jQuery,既阻止默认行为又停止冒泡
2 $("#testA").on('click',function(){
3 return false;//当然 也阻止了事件本身
4 });
总结使用方法
当需要停止冒泡行为时
function stopBubble(e) {
//如果提供了事件对象,则这是一个非IE浏览器
if ( e && e.stopPropagation ){
e.stopPropagation(); //因此它支持W3C的stopPropagation()方法
}else{
window.event.cancelBubble = true; //否则,我们需要使用IE的方式来取消事件冒泡
}
}
当需要阻止默认事件时
function stopDefault( e ) {
if ( e && e.preventDefault ){
e.preventDefault(); //阻止默认浏览器动作(W3C)
}else {
window.event.returnValue = false; //IE中阻止函数器默认动作的方式
}
return false;
}
最后的解决方法:
让我们回顾一下最初的问题,可能部分浏览器把事件的useCapture默认为true,导致点击子元素时父元素的事件先响应了,于是我的办法是在父元素的事件里进行判断
比如容器为
#a,
动态插入的元素为#b,
在#a上监听click事件,判断event.target.id是不是等于b即可,如果.b
class这种,以此类推。
我们经常能遇到阻止冒泡,但是阻止捕获一般不会遇到,因为浏览器一般默认就给我们阻止了,只能说什么情况都有啊,万事还是得考虑周全。
js 事件详解 冒泡的更多相关文章
- 第三天:JS事件详解-事件流
学习来源: F:\新建文件夹 (2)\HTML5开发\HTML5开发\04.JavaScript基础\6.JavaScript事件详解 学习内容: 1)基础概念 2)举例说明: 代码如上,如果用事件 ...
- JS事件详解
hello,我是沐晴,最近呢,来总结一下 JS中的常用的事件,希望我们都能一起查漏补缺. 焦点事件 焦点事件在表单中经常用到,那什么是焦点呢?比如我们文本框里面的有光标的时候,就是获得了焦点,我们就可 ...
- Js 事件详解
1.事件流 1.1 事件流 描述的是在页面中接受事件的顺序 1.2 事件冒泡 由最具体的元素接收,然后逐级向上传播最不具体的元素的节点(文档) 1.3 事件捕获 最不具体的节点先接收事件,而最具体的节 ...
- js中鼠标滚轮事件详解
js中鼠标滚轮事件详解 (以下内容部分内容参考了http://adomas.org/javascript-mouse-wheel/ ) 之前js 仿Photoshop鼠标滚轮控制输入框取值中已使用 ...
- js keyup、keypress和keydown事件 详解
js keyup.keypress和keydown事件 详解 js keyup.keypress和keydown事件都是有关于键盘的事件 当一个按键被pressed 或released在每一个现代浏 ...
- react第五单元(事件系统-原生事件-react中的合成事件-详解事件的冒泡和捕获机制)
第五单元(事件系统-原生事件-react中的合成事件-详解事件的冒泡和捕获机制) 课程目标 深入理解和掌握事件的冒泡及捕获机制 理解react中的合成事件的本质 在react组件中合理的使用原生事件 ...
- JavaScript事件详解-jQuery的事件实现(三)
正文 本文所涉及到的jQuery版本是3.1.1,可以在压缩包中找到event模块.该篇算是阅读笔记,jQuery代码太长.... Dean Edward的addEvent.js 相对于zepto的e ...
- JAVASCRIPT事件详解-------原生事件基础....
javaScirpt事件详解-原生事件基础(一) 事件 JavaScript与HTML之间的交互是通过事件实现的.事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间,通过监听特定事件的发生,你能 ...
- DOM——事件详解
事件 事件:触发-响应机制 事件三要素 事件源:触发(被)事件的元素 事件名称: click 点击事件 事件处理程序:事件触发后要执行的代码(函数形式) 事件的基本使用 var box = docu ...
随机推荐
- Spring Batch事务处理
事务模型描述 1.step之间事务独立 2.step划分成多个chunk执行,chunk事务彼此独立,互不影响:chunk开始开启一个事务,正常结束提交.chunk表示给定数量的item的操作集合,主 ...
- Android——黑名单管理
DBHelper.java package com.example.chenshuai.test; import android.content.Context; import android.dat ...
- NETCONF+Yang配置TSN
NETCONF用来替换SNMP,是一个网管协议.YANG是NETCONF的数据建模语言,可以使用Yang模式的文本配置网关,从而通过NETCONF协议管理网关. NETCONF+Yang可用于TSN( ...
- QPushButton取消按压后文字下沉效果
1.下沉原因 1.1.QPushButton源码 void QPushButton::initStyleOption(QStyleOptionButton *option) const { if (d ...
- spring+dubbo整合
创建公共接口或者project用到的一些bean.我这里就仅仅是创建了一个接口.project文件夹例如以下: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQ ...
- 【css】绝对定位的元素在 ie6 下不显示
问题描述: 在 ie6 中如果一个浮动元素与绝对定位元素相邻的话,在某些情况下绝对定位元素将会消失. 产生原因: 只有当绝对定位元素的邻近浮动元素的宽度大于父层宽度减 3 时(即如果父层宽度是 300 ...
- "No user exists for uid 501"
"No user exists for uid 501" 问题表现:git操作远端失败. iterm2的问题,更改了配置可能导致这个问题,最简单的解决办法,退出客户端后重启.重 ...
- Javascript Notes
Get started with Programming Javascript中的保留字,但是大部分却没在这个语言中使用.undefined,NaN,Infinity也应该算保留字. abstract ...
- 安卓程序代写 网上程序代写[原]C语言基础
C 作者:han1202012 发表于2013-11-1 19:53:29 原文链接 阅读:28 评论:0 查看评论
- activity 与 fragment生命周期
一.Activity的生命周期图: 二.Fragment生命周期图 三.对比图 Log数据 Activity﹕ onCreateFragment﹕ onAttachFragment﹕ onCre ...