js事件委托及冒泡

1.什么是事件流?

事件流描页面中接收事件的顺序,简单来说就是事件从捕获-->处理-->冒泡的一个过程。事件冒泡触发顺序是从下至上,事件捕获的触发顺序是从上至下。(先捕获后冒泡)。而早期的IE和Netscape提出了完全相反的事件流概念,IE事件流是事件冒泡,而Netscape的事件流就是事件捕获。

 

2.什么是事件冒泡?

事件冒泡是事件传递方式的一种现象,就是🐟吐泡泡一样肯定是慢慢由水底浮到水面,事件传递顺序是自身dome 》 父dom 》body 》html 》window。

 

3.什么是事件委托?

事件委托是利用事件冒泡的特性,将本应该注册在子元素上的处理事件注册在父元素上,触发子元素时发现其本身没有相应事件就转而触发父元素的事件。

优点:

  1. 减少DOM操作,提高性能。
  2. 添加的子元素会自动有相应的处理事件。

缺点:

  1. 事件委托基于冒泡(部分浏览器不支持 IE)。 
  2. 层级过多,冒泡过程中可能被中间层阻止,事件过多时判断复杂 。

4.事件委托写法

el.addEventListener("click", function(){
    console.log('事件委托-方法')
});

el.addEventListener('click', {
  handleEvent: function (event) {
    console.log('事件委托-EventListener接口对象');
  }
});

//IE 8 及更早 IE版本兼容写法
var x = document.getElementById("myBtn");
if (x.addEventListener) x.addEventListener("click", myFunction);
else if (x.attachEvent) x.attachEvent("onclick", myFunction);


 // 移除事件
function removeEvent (element, type, handler) {
    if (element.removeEventListener) element.removeEventListener(type, handler, false);
    else element.detachEvent('on' + type, handler);  //it
},
// 阻止事件 (主要是事件冒泡,因为IE不支持事件捕获)
function stopPropagation (ev) {
    if (ev.stopPropagation) ev.stopPropagation();
    else ev.cancelBubble = true;   //ie
},
// 取消事件的默认行为
function preventDefault (event) {
    if (event.preventDefault) event.preventDefault();
    else event.returnValue = false;  //ie
},

addEventListener有三个参数分别是:

  • type :监听事件类型(事件类型大全
  • listener :监听事件触发回调(方法或者EventListener接口对象)
  • 参数三有两种版本
    • options (古老的版本目前基本肯定不会遇到-了解下没有坏处)
      • capture :listener会在该类型的事件捕获阶段传播到该EvenTarget时触发
      • once:listener在添加之后最多被调用一次
      • passive:true时,listener永远不会调用preventDfault()
      • mozSystemGroup:listener被添加到systemgroup
    • useCapture:是否要先于下面的EventTarget调用该listener()。true回调在捕获阶段执行,false事件在冒泡阶段执行。

高级写法

function delegate(element, eventType, selector, fn) {
    function addParent(){
        let el = e.target
		while (!el.matches(selector)) {
		    if (element === el) {
		       el = null
		        break
		     }
		     el = el.parentNode
		}
		el && fn.call(el, e, el)
    }
    if(element.addEventListener){
        element.addEventListener(eventType, e => {
	        addParent();
	    },false )
    }else{  //ie
        element.attachEvent('on'+eventType, e => {
	        addParent();
	    },false )
    }
	return element
}
		
delegate(document.getElementById('1'), 'click', 'ul', function() { 
	alert($(this).text());
});

5.vue中的事件委托

vue交流社区中有人提问后大佬给出的解答 Is event delegation necessary?。vue内部是没有处理事件委托的。并且转换为虚拟dom的时候也并未有相关处理(这里建议大家自己去阅读下源码,我看的有点久了已经记不清楚了)。

//建议写法,听过data-index来区分

<ul @click="uLClick">
    <li v-for="(item, index) in list" :data-index="index">{{index}}</li>
</ul>

 

6.后续补充vue虚拟dom转换源码,及vue事件处理源码

 

 

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
事件冒泡是指当一个元素上的事件被触发时,该事件会从最内层的元素开始向父级元素逐级触发,直到触发到最外层的元素为止。事件冒泡可以通过使用 `event.stopPropagation()` 方法来停止继续向上冒泡事件委托则是利用事件冒泡的特性,将事件处理程序绑定在父级元素上,通过判断事件源来执行相应的操作。这种方式可以减少事件处理程序的数量,优化性能,特别适用于动态添加或删除子元素的情况。 举个例子来说,假设有一个父级元素 ul,里面包含多个子元素 li,我们希望点击每个 li 元素时能执行相应的操作。传统的方式是给每个 li 元素都绑定点击事件,但是如果 li 元素很多的话会导致事件处理程序过多。而使用事件委托的方式,我们只需要给 ul 元素绑定一个点击事件,并通过判断事件源是哪个 li 元素来执行对应的操作。 ```javascript // 传统方式 const lis = document.querySelectorAll('li'); lis.forEach(li => { li.addEventListener('click', function() { // 执行操作 }); }); // 事件委托 const ul = document.querySelector('ul'); ul.addEventListener('click', function(event) { const target = event.target; if (target.tagName === 'LI') { // 执行操作 } }); ``` 通过事件委托,我们只需要绑定一个事件处理程序,即使动态添加或删除了 li 元素,也不需要重新绑定事件处理程序,从而提高了性能和代码的可维护性。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值