JavaScript实现事件委托

事件流分为三个阶段,依次为捕获阶段(父->子)、目标阶段、冒泡阶段(子->父),事件触发顺序为捕获阶段–目标阶段–冒泡阶段;

平时给元素绑定事件一般是直接写到属性上(即0级事件处理程序)或是addEventListener()监听事件(2级事件处理程序)。但有些应用场景以上方法可能不太管用,比如给后来动态添加的元素绑定事件监听。这时就可以使用事件委托了(也叫事件代理)。事件委托简单通俗理解就是,给外层元素绑定事件,然后利用事件冒泡,针对当前触发的元素执行相应的函数。

    <ul class="list">
        <li>第一条</li>
        <li>第二条</li>
        <li>第三条</li>
    </ul>
    <button class="btn">添加列表</button>
    <script>
        var list = document.querySelector('.list');
        var btn = document.querySelector('.btn');
 
        btn.onclick = function(){
            var li = document.createElement('li');
            li.innerHTML = '<p>大家好<a href="javascript:;">才是真的好</a></p>'
            list.appendChild(li);
        }
        
 
        on(list, 'click', 'a', function(){
            alert(this.innerText);
        })
 
        function on(el, eventType, selector, fn){
            if(fn === undefined){       //如果只传三个参数,即为自身绑定事件
                fn = selector;
                selector = null;
                el.addEventListener(eventType, fn, false);
            }else{      //如果传入四个参数,即为事件委托,selector为事件目标
                el.addEventListener(eventType, function(e){
                    if(e.target.matches(selector)){     //如果当前时间目标与selector匹配
                        fn.call(e.target, e);
                    }
                }, false);
            }
        }

// 方法二
 function delegate(element, eventType, selector, fn) {
        element.addEventListener(eventType, e => {
            let el = e.target
            while (!el.matches(selector)) {
                if (element === el) {
                    el = null
                    break
                }
                el = el.parentNode
            }
            el && fn.call(el, e, el)
        })
        return element
    }
    </script>

 示例:通过点击每张图片,弹出相应的视频

image.png

 <div class="flex-contain-Main-top-flex" id="playModel_1">
		<div class="flex-img1">
         <img src="./assets/img/srcoll1.jpg" alt="">
    </div>
    <div class="flex-img2">
          <img src="./assets/img/srcoll2.jpg" alt="">
    </div>
    <div class="flex-img3">
         <img src="./assets/img/srcoll3.jpg" alt="">
     </div>
     <div class="flex-img4">
          <img src="./assets/img/srcoll4.jpg" alt="">
     </div>
 </div>
 <!--   dialog 弹窗模块 -->
<div id="dialog">
   <div class="shadow"></div>
    <div class="site-content cf">
        <div class="boxed-group">
              <h3>视频播放</h3>
               <div class="boxed-group-inner">
                    <video id="myvideo" style="width:100%; height:100%; object-fit: fill" controls>
                    </video>
                 </div>
                <div class="footer">
                     <button href="#" class="btn btn-danger boxed-action" id="cancel"
                                        onclick="cancel()">X</button>
                  </div>
           </div>
      </div>
 </div>

 let videoList = [
        'http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4',
        'http://vjs.zencdn.net/v/oceans.mp4',
        'https://media.w3.org/2010/05/sintel/trailer.mp4',
        'http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4'
    ];
    let dialog = document.getElementById("dialog");
    let player = document.getElementById('playModel_1');
    let video = document.getElementById('myvideo');
    dialog.style.display = "none";

    on(player, 'click','img',function (e) {
        let parent =  e.target.parentElement;
        let index =Array.prototype.indexOf.call(parent.parentNode.children, parent);
        dialog.style.display = '';
        video.src = videoList[index]

    });
    function on(el, eventType, select, fn) {
        if (fn === undefined){ // 自身绑定
            fn = select;
            select = null;
            el.addEventListener(eventType, fn , false)
        }else {
            el.addEventListener(eventType,function (e) {
                if (e.target.matches(select)){
                    fn.call(e.target,e)
                }
            },false)
        }
    }
    function cancel() {
        let videoPlayer = document.getElementById('myvideo');
        videoPlayer.pause();
        dialog.style.display = "none";
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值