js事件委托

什么是事件委托

利用冒泡的机制,将某一类型的操作委托给父级统一管理,然后根据事件源(target)去完成某一子项的操作。

为什么要使用事件委托

dom的事件我们习惯上直接绑定到dom上,但是如果需要绑定事件的dom很多,那会直接影响页面的性能,频繁的对dom进行事件绑定,本身就是消耗性能的事情。从资源消耗角度来看,每个方法本身都是对象,都要占据空间,所以方法越多,空间耗费越大,那么利用委托就是势在必行的。例如,有n个li要执行click操作,我们可能会使用for循环来完成,在操作上似乎没有多麻烦,但如果考虑前面提到的性能和资源耗费方面,那就是非常严重的了,尤其是当n很大的时候。这时候我们就需要委托,就是直接将li的click都绑定到li的父级ul上,由父级进行统一管理,用事件源(target)作为判断条件,以便于对某一个li做操作。
示例1

 	<!-- 示例1 -->
    <ul id='demo1'>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
    <script>
        var domUl1 = document.getElementsByTagName('ul')[0];
        var domLi = domUl1.getElementsByTagName('li');
        // 不使用委托
        for (var i = 0; i < domLi.length; i++) {
            domLi[i].onclick = function () {
            	// 这里其实也存在一个闭包问题,i共用,在使用时已变成5
                console.log('不委托', i);
            }
        }
    </script>

不使用委托,点击li的结果:
在这里插入图片描述

使用委托,向ul绑定事件,通过事件源判断对具体某个li进行操作。如果你对事件源还不了解,可以console.log(事件源)查看一下。

		var domUl1 = document.getElementById('demo1');
        domUl1.onclick = function (event) {
         	var event = event || window.event; // 事件对象,保证低版本ie兼容性
            var target = event.target || event.srcElement; // 事件源,保证低版本ie兼容性
            console.log('委托', target.innerHTML);
        }

使用委托后,点击li的结果:
在这里插入图片描述
示例2
对于新加入节点,在不使用委托的情况下,对li利用for循环绑定的事件在新结点上将不会生效,除非重新执行for循环,再次绑定才有效。

<!-- 不使用委托,新增元素不会绑定方法 -->
	<div>
        <input type="button" value='添加li' onclick="addLi()" />
        <ul id='demo2'>
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
        </ul>
    </div>
    <script>
        var domUl2 = document.getElementById('demo2');
        var domLi2 = domUl2.getElementsByTagName('li');
        var n = 5;
        //鼠标移入值加1,移出值减1
        for (var i = 0; i < domLi2.length; i++) {
            domLi2[i].onmouseover = function (e) {
                // this指向触发方法的dom
                this.innerHTML++;
            };
            domLi2[i].onmouseout = function (e) {
                // this指向触发方法的dom
                this.innerHTML--;
            }
        }
        // 添加新i
        function addLi() {
            var domLiItem = document.createElement('li');
            domLiItem.innerHTML = ++n;
            domUl2.appendChild(domLiItem);
        }
    </script>

这里我们对li添加onmouseover 和 onmouseout 事件,使li的值“++”或“–”,当点击【添加li】按钮新增li后,新增的li并不会触发之前绑定的事件, 除非我们在添加li后重新执行for循环绑定,这不仅让代码变得冗余,也浪费性能。**使用委托,对于新增元素添加的事件处理函数依然生效。**如下:

		// 添加新i
        function addLi() {
            var domLiItem = document.createElement('li');
            domLiItem.innerHTML = ++n;
            domUl2.appendChild(domLiItem);
        }
        // 委托------------
        domUl2.onmouseover = function (event) {
            var event = event || window.event; // 事件对象,保证低版本ie兼容性
            var target = event.target || event.srcElement; // 事件源,保证低版本ie兼容性
            if (target.nodeName === "LI") {  // nodeName判断节点具体时什么元素
                target.innerHTML++;
            }
        }
        domUl2.onmouseout = function (event) {
            var event = event || window.event; // 事件对象,保证低版本ie兼容性
            var target = event.target || event.srcElement; // 事件源,保证低版本ie兼容性
            if (target.nodeName === "LI") {  // nodeName判断节点具体时什么元素
                target.innerHTML--;
            }
        }

示例3

对于子元素都事件执行内容不同,但事件相同的委托

<!-- 不使用委托,当子元素较多的时候,添加的事件越多 -->
	<div id="demo3">
  	    <input type="button" id='add' value="添加">
        <input type="button" id='modify' value="修改">
        <input type="button" id='del' value="删除">
    </div>
    <script>
		 var add = document.getElementById("add");
         var modify = document.getElementById("modify");
         var del = document.getElementById("del");
         add.onclick = function () {
             console.log('add');
         };
         modify.onclick = function () {
             console.log('modify');
         };
         del.onclick = function () {
             console.log('del');
         };
    </script>

使用委托后的代码:

			// 委托
			var demo3 = document.getElementById("demo3");
            demo3.onclick = function (event) {
                var event = event || window.event;
                var target = event.target || event.srcElement
                switch (target.id) {
                    case 'add':
                        console.log('add');
                        break;
                    case 'modify':
                        console.log('modify');
                        break;
                    case 'del':
                        console.log('del');
                        break;
                }
            }

示例4
多层嵌套,对某一层绑定事件。这里是对li绑定事件

	<ul id="demo4">
        <li>
            <p>我是ul下的li下的p标签</p>
        </li>
        <li>
            <a href="https://blog.csdn.net/Kindergarten_Sir">我是ul下的li下的a标签</a>
        </li>
        <li>
            <div>我是ul下的li下的div标签</div>
        </li>
        <li>我是ul下的li标签</li>
    </ul>
    <script>
	    var demo4 = document.getElementById("demo4");
        demo4.onclick = function (event) {
             var event = event || window.event; // 事件对象,兼容低版本ie
             var target = event.target || event.srcElement; // 事件源,兼容低版本ie
             event.preventDefault();
             while (target.nodeName !== 'LI') {
                  target = target.parentNode; // 父级
             }
             console.log('我是li');
         }
    </script>

以上是4种不同情况的委托。
相关学习内容推荐:你知道阻止默认行为、冒泡的封装吗?
相关学习内容推荐:你知道事件执行顺序,捕获、冒泡吗?

如果对你有帮助,可以点赞、收藏+关注哦~😘

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值