第一句子网 - 唯美句子、句子迷、好句子大全
第一句子网 > 事件(阻止事件传播 阻止默认事件 事件源对象 事件委托)

事件(阻止事件传播 阻止默认事件 事件源对象 事件委托)

时间:2021-10-08 18:08:03

相关推荐

事件(阻止事件传播 阻止默认事件 事件源对象 事件委托)

阻止事件传播

阻止事件传播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 = trueIE低版本

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也能阻止默认事件

DOM0级事件中,也能阻止掉默认事件

document.oncontextmenu = function(e){console.log('huashneg');return false;}

阻止默认事件:掉鼠标右键默认菜单

鼠标右键点击了4会

也能取消a标签的默认事件

var oA = document.getElementsByTagName('a')[0];oA.onclick = function(){return false;//取消a标签的默认事件};

那可以DOM2级事件中,能阻止默认事件吗??

var oA = document.getElementsByTagName('a');document.addEventListener('contextmenu',function(){return false;},false);

答案是不能的:在DOM2级事件中不能通过,return false阻止默认事件

阻止默认事件e.returnValue = falseIE低版本(IE8一下)

document.oncontextmenu = function(e){console.log('huashneg');e.returnValue = false;//取消IE及其以下的默认事件}

e.returnValue = falseIE低版本(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.targetIE8以上高本版浏览器

那么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.srcElementIE低版本找到事件源对象,获取的是元素的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;//阻止浏览器的默认行为}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。