事件代理又叫事件委托,JavaScript高级程序设计上讲:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
但如果我们不想实现事件委托,却发生了事件冒泡呢?
在遇到父元素和子元素都有点击事件的情况下,点击父元素(父元素范围 > 子元素)是没有任何问题的,但当我们点击子元素时就不得不面临“事件冒泡”的问题了。但开心的是,事件冒泡是可以取消的。
原本只是想解决demo中的一个小问题,解决时候发现,这不正是事件冒泡问题吗?DOM事件委托都快忘记了,正好趁此把笔记拿出来再梳理一遍。
以下是我遇到事件冒泡问题的场景:
kbdX.onclick = function(keyb){ keyi = keyb.target.innerText[0].toLowerCase() website = hash[keyi]; console.log(website) // location.href = 'http://' + website; window.open('http://' + website, '_blank'); } buttonXE.textContent = 'E'; buttonXE.id = keys[i][j]; buttonXE.onclick = function(keyd){ // keyd.target是用户点击的元素 console.log(keyd.target.id) keyX = keyd.target.id new_website = prompt('更改按键对应的导航网址') hash[keyX] = new_website // hash变更 localStorage.setItem('update_website', JSON.stringify(hash)); keyd.stopPropagation(); // 阻止冒泡事件 location.reload(); // 页面刷新重载 // console.log(hash) } divX.appendChild(kbdX); kbdX.appendChild(buttonXE);
显然 kbdX 是 buttonXE 的父级,当我们点击 buttonXE 时发现, kbdX点击事件同样会被触发,这就是因为发生了事件冒泡。
那么先让我们来了解一下什么是事件冒泡呢?
从外向内找监听函数,事件捕获;(网景提出) 从内向外找监听函数,事件冒泡。(IE5提出)
同时我们还要区分target VS currentTarget :
e.target:用户操作的元素
e.currentTarget:程序员监听的元素
this是ecurrentTarget,所以不推荐使用this,担当只有一个div 被监听(不考虑父子同时被监听),fn分别在捕获阶段和冒泡阶段监听click事件,用户点击的元素就是开发者监听的。
取消事件冒泡
捕获不可以取消,冒泡可以 e.stopPropagation()可中断冒泡,浏览器不再向上走。
这里我就是采用的e.stopPropagation()直接中断冒泡,阻止了 kbdX点击事件的发生。
有些事件不可取消冒泡 ,在scroll event中,Bubble---是否冒泡,Cancelable---开发者是否可以取消冒泡
举例:如何阻止冒泡 scroll事件不可取消冒泡,阻止scroll默认动作没用,因先有滚动才有滚动事件;要阻止滚动,可阻止wheel和touchstart的默认动作;注意需要找准滚动条所在元素;若滚动条还能用,用CSS让滚动条display: none
CSS使用overflow: hidden可以直接取消滚动条 此时JS依然可以修改scrollTop
当然我们也可以自定义事件,这就属于DOM事件委托的拓展了,以后学习到会再整理。