事件(阻止事件传播、阻止默认事件、事件源对象、事件委托)
阻止事件传播
阻止事件传播e.stopPropagation()
谷歌浏览器
阻止事件传播(冒泡阶段)
var oBig = document.getElementById('big');var oSmall = document.getElementById('small');oBig.addEventListener('click',function(){//事件处理函数console.log('big 冒泡阶段我被点击了');},false);//false事件冒泡阶段触发oSmall.addEventListener('click',function(){//事件处理函数console.log('small 被点击了');},false);//false事件冒泡阶段触发
点击small的盒子打印的结果
点击small触发small的事件处理函数,然后big的事件处理函数也被触发了,因为事件冒泡机制才触发了big的事件处理函数
因为事件冒泡机制才触发了big
的事件处理函数,那么该怎么阻止small
事件冒泡??? (冒泡阶段)
var oBig = document.getElementById('big');var oSmall = document.getElementById('small');oBig.addEventListener('click',function(){console.log('big 冒泡阶段我被点击了');},false);oSmall.addEventListener('click',function(e){e.stopPropagation();//阻止事件传播console.log('small 被点击了');},false);
这样写上e.stopPropagation()
着句代码small的点击事件就不会往上冒泡了,自然而然就不会被big所捕捉到,那么就不会触发big的事件处理函数了
点击small的打印结果
阻止事件传播(捕获阶段)
var oBig = document.getElementById('big');var oSmall = document.getElementById('small');oBig.addEventListener('click',function(){console.log('big 捕获阶段我被点击了');},true);oSmall.addEventListener('click',function(e){e.stopPropagation(); console.log('small 被点击了');},true);
点击small的盒子打印的结果
点击small,首先事件监听器的第3个参数写的是true,true是在事件捕获阶段触发事件处理函数
点击small是从上到下捕获的(document—>html—>body–>big—>small),那么点击small肯定会触发big的事件处理函数。
因为true是事件捕获阶段,所以他会从上到下看,先看big有没有对应的事件处理函数有就会触发,然后因为点击了small的事件处理函数
那么该怎么阻止事件捕获阶段??? (捕获阶段)
var oBig = document.getElementById('big');var oSmall = document.getElementById('small');oBig.addEventListener('click',function(e){e.stopPropagation(); //阻止事件传播console.log('big 捕获阶段我被点击了');},true);oSmall.addEventListener('click',function(){console.log('small 被点击了');},true);
捕获阶段:捕获到document(没有对应的事件处理函数)---->捕获到html(没有对应的事件处理函数)- -->捕获到body(没有对应的事件处理函数)- - ->捕获到big(有对应的事件处理函数)加上e.stopPropagation()
阻止事件传播代码就不会触发small的事件处理函数了- - ->捕获到small(有对应的事件处理函数)不会被big传播了
点击small的打印结果
阻止事件传播e.cancelBubble = true
IE低版本
var oBig = document.getElementById('big');var oSmall = document.getElementById('small');oBig.attachEvent('onclick',function(){console.log('big 捕获阶段我被点击了');},true);oSmall.attachEvent('onclick',function(e){e.cancelBubble = true;//IE低版本阻止事件传播console.log('small 被点击了');},true);
点击small的打印结果
在IE低版本e.cancelBubble = true
可以阻止事件传播
封装stopBubble(e)
兼容函数
function stopBubble(e){if(e.stopPropagation){ //谷歌e.stopPropagation()}else{ //IE低版本e.cancelBubble = true}}
阻止默认事件
什么是网页的默认事件???: 右键出菜单、图片拖动、a标签跳转、表单提交这些网页的默认事件
阻止默认事件 e.preventDefault()
谷歌 (IE8以上)
那该怎么阻止右键出菜单的默认事件呢??
document.oncontextmenu = function(e){console.log('huashneg');e.preventDefault();//取消默认事件};
鼠标右键点击了5从huasheng,没有出菜单
那该怎么阻止a标签的默认跳转事件
点击a标签,a标签会跳转到另一个页面,这是a标签的默认行为
var oA = document.getElementsByTagName('a')[0];//获取a标签元素oA.onclick = function(e){//个a标签正个点击事件任何在取消默认事件e.preventDefault();//取消默认事件};
return false
也能阻止默认事件
在DOM
0级事件中,也能阻止掉默认事件
document.oncontextmenu = function(e){console.log('huashneg');return false;}
阻止默认事件:掉鼠标右键默认菜单
鼠标右键点击了4会
也能取消a标签的默认事件
var oA = document.getElementsByTagName('a')[0];oA.onclick = function(){return false;//取消a标签的默认事件};
那可以DOM
2级事件中,能阻止默认事件吗??
var oA = document.getElementsByTagName('a');document.addEventListener('contextmenu',function(){return false;},false);
答案是不能的:在DOM2级事件中不能通过,return false
阻止默认事件
阻止默认事件e.returnValue = false
IE低版本(IE8一下)
document.oncontextmenu = function(e){console.log('huashneg');e.returnValue = false;//取消IE及其以下的默认事件}
e.returnValue = false
IE低版本(IE8一下)的可以阻止默认事件
封装cancelHandler
兼容性函数
//这个函数的作用是阻止浏览器默认行为 并且兼容不同的浏览器function cancelHandler(e){if(e.preventDefault){ //谷歌e.preventDefault()}else{ //IE低版本e.returnValue = false}}
事件源对象
事件源对象 --> 指向触发事件源头的节点
var oBig = document.getElementById('big');var oSmall = document.getElementById('small')oBig.addEventListener('click',function(){console.log('oBig');},false);oSmall.addEventListener('click',function(){console.log('oSmall');},false);
点了oSmall
打印了两个,那么怎么知道到底你是点击了那个呢??
var oBig = document.getElementById('big');var oSmall = document.getElementById('small')oBig.addEventListener('click',function(e){console.log(e.target);//e.target是指事件的源头(节点)},false);oSmall.addEventListener('click',function(){},false);
点击small然后这个点击事件会冒泡到big上面,然后big上面的事件处理函数就会触发,那么现在的事件对象的target属性,就是用来指向这您初始用户点了谁,到底是那个节点引起了这个事件或者说是那个节点触发了这个事件。
是small这个节点触发了这个事件,因为点击了这个节点事件冒泡到big上面的事件处理函数一个属性能记录到底是触发了谁才使得我这个事件处理函数被触发了。
例子:
var oBig = document.getElementById('big');var oSmall = document.getElementById('small')document.body.addEventListener('click',function(e){console.log(e.target);},false)oBig.addEventListener('click',function(e){console.log(e.target);},false);oSmall.addEventListener('click',function(e){console.log(e.target);},false);
点击small
你是点击了small,因为事件冒泡的机制big会捕获的,事件在往上冒document.body也会捕获的,然后这个源头到底是谁,是small(他获取的是一个DOM节点)
点击big
你是点击了big,因为事件冒泡的机制docume.body会捕获的,然后会往上冒找到html看看html有没有对应的事件处理函数(有就会触发没有就不会)
点击document.body
你点击了document.body,冒泡机制往上找有没有对应的事件和事件处理函数,一看html和document没有对应的事件和事件处理函数就不会触发
event.target
IE8以上高本版浏览器
那么IE8以下的底版版浏览器怎么找到源对象
var oBig = document.getElementById('big');var oSmall = document.getElementById('small')oBig.addEventListener('click',function(e){console.log(e.srcElement);},false);oSmall.addEventListener('click',function(e){console.log(e.srcElement);},false);
e.target
谷歌 和 e.srcElement
IE低版本 找到事件源对象,获取的是元素的DOM,有相对应的事件处理函数的DOM就会触发谁,没有就不会触发
兼容事件源对象的,兼容写法
var oBig = document.getElementById('big');oBig.addEventListener('click',function(e){var target = e.target || e.srcElement;//兼容写法console.log(target)},false);
事件委托
那怎么点击对应的文字,出对应的索引呢??
var aLi = document.getElementsByTagName('li');//获取li元素for(var i=0;i<aLi.length;i++){//遍历每个li的lengthaLi[i].onclick = function(){console.log(i);};};
那为什么点击一次li打印一次5呢??
因为for
循环是同步代码,点击事件里面的回调函数执行是异步代码,那么先执行同步代码在执行异步代码,等同步代码执行完是i=5
,然后在执行点击事件里面的回调函数(异步代码),那么每点击一个li就会打印一次5
那么怎么让每次点击之后打印对应的索引呢??
只所以打印出来5,点击了第一个li,会触发回调函数里面的i,那么这个回调函数执行的时候AO中是没有i的,那我会从GO中里找,GO中的i=5
那我会从GO中拿到i=5,那么每次点击li就会打印出来5
这时我们需要延长这个点击事件的函数作用域链,让这个点击事件的外部还有一个作用域
var aLi = document.getElementsByTagName('li');//获取li元素for(var i=0;i<aLi.length;i++){***加粗样式***//遍历每个li的length(function(i){//延长作用域链//AO:i=0aLi[i].onclick = function(){console.log(i);//我没有i我会去父级AO中找是i=0};})(i);};
从作用域链的角度来说,当前的点击事件里面的回调函数中的所处的环境是上面这个函数的环境
那么我们不用这种形式也能打印出来对应的索引
var aLi = document.getElementsByTagName('li');//获取li元素//遍历每个li的lengthfor(var i=0;i<aLi.length;i++){//aLi[i]是一个节点,是节点我们就可以给他自定义一个属性aLi[i].index = i;//给aLi[i]设置自定义属性indexaLi[i].onclick = function(){console.log(this.index);};//每次打印就查询this里面的index属性//this指向自身};
这样写是有一个弊端:现在是给5个li的上面onclick属性都赋值了一个函数,也就是在内存中开辟了5个空间存放了5个函数,然后把第一个函数给了aLi[i].onclick
属性以此类推
通过for循环的形式,给5个li中的每一个li都绑定了一个函数,这种形式在内存中开辟了5个空间,然后函数作为引用值是在内存占据空间的。
那么我们怎么避免这种占据大量空间那该怎么写??
可以使用事件委托的形式
那什么是事件委托呢??
利用事件冒泡的原理把子级的事件委托给祖先元素
var oUl = document.getElementsByTagName('ul')[0];//获取ul元素oUl.onclick = function(e){console.log(e.target.innerText-1);};//innerText打印对应的文本
通过事件冒泡这种机制,能够触发父元素的事件处理函数,同样的通过事件源对象我有能够早到自己(子元素),在父元素的事件处理函数中操纵自己,把这个事件委托给父元素。
那么添加新的子元素时怎么做事件委托
var oUl = document.getElementsByTagName('ul')[0];//获取Ul元素var aLi = document.getElementsByTagName('li');//获取li元素for(var i=0;i<aLi.length;i++){aLi[i].index = i;aLi[i].onclick = function(){console.log(this.index);};};var oLi = document.createElement('li');//创建节点oUl.appendChild(oLi);//添加节点oLi.innerText = '6';//给节点添加内容
为什么新加的li没有打印???
因为你在for循环只给5个li绑定了对应的事件和对应的事件处理函数,然后后面新增的li元素没有绑定对应的事件,对应新增的li是没有的。
用事件委托的方式
var oUl = document.getElementsByTagName('ul')[0];//获取Ul元素var oLi = document.createElement('li');//创建节点oUl.appendChild(oLi);//添加节点oLi.innerText = '6';//给节点添加内容oUl.onclick = function(e){console.log(e.target.innerText-1);};//通过事件委托的方式
当你新增节点的时候不用绑定对应的事件,事件委托自动的给你绑定上,他可以在内存中开辟一个空间存储着子元素的所有要绑定的事件处理函数。
优点
- 不需要循环绑定每个子元素,可以节约浏览器性能
- 添加新的子元素时,不需要再给新元素绑定事件
拖拽图片
/** 拖拽使用的三个事件* onmousedown* onmousemove* onmouseup* */var oImg = document.getElementsByTagName('img')[0];oImg.onmousedown = function(e){e = e||winodw.event; //兼容事件对象var startX = e.clientX; //记录鼠标按下时的水平位置var startY = e.clientY; //记录鼠标按下时的竖直位置var startLeft = this.offsetLeft; //记录鼠标按下时的图片的初始水平位置var startTop = this.offsetTop; //记录鼠标按下时的图片的初始竖直位置document.onmousemove = function(e){e = e||winodw.event; //兼容事件对象var moveX = e.clientX; //记录鼠标移动时的水平位置var moveY = e.clientY; //记录鼠标移动时的竖直位置oImg.style.left = startLeft + moveX - startX +'px';oImg.style.top = startTop + moveY - startY +'px';}oImg.onmouseup = function(){document.onmousemove = null;//解除onmousemove的事件处理函数}return false;//阻止浏览器的默认行为}
事件(阻止事件传播、阻止默认事件、事件源对象、事件委托)相关推荐
- 事件注册方法、阻止默认事件、事件对象、事件冒泡:事件委托、事件捕获、重置表单
dom两种注册事件语法 1.点语法注册事件: 事件源.事件类型 = 事件处理函数 特点:不能注册'同名事件', 否则会覆盖 2.addEventListener 事件源.addEventListene ...
- 【EventBus】事件通信框架 ( 订阅类-订阅方法缓存集合 | 事件类型-订阅者集合 | 订阅对象-事件类型集合 )
文章目录 前言 一.订阅类-订阅方法缓存集合 二.事件类型-订阅者集合 三.订阅对象-事件类型集合 前言 首先声明几个数据结构 , 参考 [EventBus]EventBus 源码解析 ( 注册订阅者 ...
- js 事件阻止传播方法,准确定位事件源
1事件冒泡 在目标元素获得机会处理事件后,事件模型检查目标元素的父元素,看是否为同类型事件建立了处理程序.如果是,则也调用父元素的处理程序.在这之后,再检查其父元素,然后父元素,然后父元素...持续不 ...
- JavaScript(11) - 阻止事件冒泡和默认行为,拖拽,事件监听器
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一.阻止事件冒泡和默认行为 二.拖拽 1, 实现拖拽相关的三大事件: 2, 实现拖拽思路: 1, 给目标元素添加onmous ...
- js添加事件、移除事件、阻止冒泡、阻止浏览器默认行为等写法(兼容IE/FF/CHROME) 转载...
js添加事件.移除事件.阻止冒泡.阻止浏览器默认行为等写法(兼容IE/FF/CHROME) 网上有关这方面的代码比较多而乱,这里整理一下并加以改进. 添加事件 01 var addEvent = ...
- js第8章事件案例:获取触发事件的元素,阻止事件冒泡和默认行为的实现、缓动的小球、图片放大特效、按Enter键切换
目录 1.获取触发事件的元素,阻止事件冒泡和默认行为的实现. (1)获取触发事件的元素 (2)阻止事件冒泡 (3)阻止事件默认行为 2.缓动的小球,实现的原理是通过定时器连续地修改当前DOM元素的某个 ...
- JavaScript事件——event对象事件冒泡 阻止默认行为事件捕获
event对象 用来获取事物的详细信息:鼠标位置.键盘按键 e.clientX 鼠标距离元素所在的X轴(左边)位置 e.clientY 鼠标距离元素所在的Y轴(顶部)位置 (左上角为0,0点) 获取e ...
- JavaScript阻止冒泡和取消默认事件(默认行为)
JavaScript冒泡和捕获是事件的两种行为,使用event.stopPropagation()起到阻止捕获和冒泡阶段中当前事件的进一步传播.使用event.preventDefault()可以取消 ...
- js阻止子元素事件_JS阻止冒泡和取消默认事件(默认行为)-前端开发博客
js冒泡和捕获是事件的两种行为,使用event.stopPropagation()起到阻止捕获和冒泡阶段中当前事件的进一步传播.使用event.preventDefault()可以取消默认事件.对于冒 ...
最新文章
- C#图片处理示例(裁剪,缩放,清晰度,水印)
- php绑定邮箱地址链接,php完美匹配邮箱、链接地址和电话号码
- 互联网创业如何与传统行业人士合作?
- 后台开发经典书籍--大型分布式网站架构设计与实践
- (73)分析 KeInitializeApc ,了解 KAPC 的初始化
- c 语言读文件数据库,C语言文件怎么读取?
- python加密程序_Python加密程序
- 判断溢出(ybtoj-字符串)
- c 5.6 mysql 配置文件_MySQL 5.6 5.7最优配置文件模板(my.ini)
- 关于Request.params的知识收藏
- Unity 3D实现帧同步技术
- Win12爆料,微软Windows 12计划3月份开始开发
- 文件关联修复命令ftype用法
- flea-common使用之本地国际化实现
- 团队作业第二次——需求分析
- [bzoj4084][Sdoi2015]双旋转字符串_hash
- 中国十大可行性研究报告公司
- ubuntu 下tftp服务器配置笔记
- 为什么现在计算机所有专业的研究生基本都搞机器学习和深度学习,国内真的需要这么多会人工智能的人才吗?...
- linux使用rm -rf删除数据后恢复
热门文章
- 图像超分——Real-ESRGAN快速上手
- 使用jQuery实现echars智能图表面板(附代码)
- lat什么意思_lat是什么意思_lat怎么读_lat翻译_用法_发音_词组_同反义词_1940年前拉脱维亚的货币单位-新东方在线英语词典...
- Rust actix aiohttp_Actix - Rust 的Actor异步并发框架
- 红黑树RBT的原理分析及实现
- App inventor—安安机器人
- 模拟器v3.1.2官方安卓版
- 快递查询 (快递100)
- 每日刷题:第四天 快乐数
- UEFI——保姆级教程的HelloWold Application