事件委托及树形菜单案例

事件委托及树形菜单案例

详情展示√

事件传播机制:目标阶段和冒泡阶段

当前元素事件行为触发,从内到外所有祖先的事件行为触发,绑定方法依次执行。

概念:

鼠标滑过显示详情:95%都是通过css实现

做法一:

每个li下面都有一个自己的详情。每个详情都是当前盒子的子元素,鼠标滑过子元素显示。

做法二:事件委托做法:

把事件绑定给大盒子即最外层容器,这样不管后代元素中哪一个子元素触发了当前事件,由于事件冒泡传播机制,document.onmouseover都会执行,拿到事件源ev.target是xxx做xxx。

…… -> body -> html -> document -> window

click效果只能用事件委托来实现。事件委托就是冒泡传播的实战应用。

click才凸显出了事件委托的强大

轮播图改造(略)

不需要等待数据加载完再绑定

只要container存在,就能进行事件绑定。按照之前的做法,总要等待页面中的dom结构渲染完了再去绑事件。

事件委托:面试必问

给动态元素绑定事件√

事件这一块的重点:

  1. 事件委托

  2. dom 2级事件绑定 事件池机制

能给动态元素绑定事件

let ul=document.querySelector('.list');
let button=document.querySelector('.add')
let liList=ul.children;

button.onclick=function(){
    // 没点新增就加5个
    let length=liList.length; // HtmlCollection是动态集合
    let fragment=document.createDocumentFragment();
    for(let i=0;i<5;i++){
        let li=document.createElement('li');
        let index=length+i+1;
        li.innerText=`第${index}个li`
        li.setAttribute('data-index',index);
        fragment.append(li)
    }
    ul.append(fragment)
}
ul.onclick=function(ev){
    if(ev.target.tagName==='LI'){
        let li=ev.target;
        alert(`我是第${li.getAttribute('data-index')}个li`)
    }
}

dom中的动态集合_空城里的往日时光的博客-CSDN博客

https://www.jianshu.com/p/b0be2479d117

而且性能提高70%

总结

事件委托是基于事件冒泡传播机制完成。事件冒泡传播指的是说,若某个元素的某个事件行为触发,那么该事件会从当前元素自下而上 从内到外沿dom树依次往上传播,即当前元素的所有祖先当前事件行为都会被触发,若绑定方法则方法依次执行。

而事件委托指的就是,比如一个父元素容器内有很多子元素,我并不是给一个个子元素单独去绑定方法,而是把方法绑定在元素容器上。

使用事件委托的好处在于:比如在某些业务场景下,使用事件委托明显有很多优势。比如有些元素是动态创建出来的,给动态元素绑事件一般都可以用事件委托。我们就可以使用事件委托把方法绑定在这些元素的父容器上,没必要等待数据加载完再一个个给元素去绑方法。要具体区分是哪个子元素触发了事件,使用event.target获取事件源即可。

首先,性能会好很多。使用事件委托比原始一个个去绑性能高出50%左右。

还有,多元素绑事件时,业务逻辑很多时候是一体的,这个时候统一用事件委托处理也会更好。

树形结构菜单

Home [zTree -- jQuery tree plug-ins.]

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>zTree</title>
    <link rel="stylesheet" href="../css/zTreeStyle.css">
    <style>
        *{
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
    </style>
</head>
<body>
    <ul class="ztree" id="ztree1"></ul>
    <script src="../js/jquery-1.4.4.min.js"></script>
    <script src="../js/jquery.ztree.all.min.js"></script>
    <script>
        let options={}
        let treeData = [
            {
                name:"test1",
                open:true,
                children:[
                    {name:"test1_1"},
                    {name:"test1_2"},
                    {
                        name:'test_3',
                        children:[
                            {name:'test_child'}
                        ]
                    }
                ]},
            {name:"test2", open:true, children:[
                    {name:"test2_1"}, {name:"test2_2"}]}
        ];
        $.fn.zTree.init($("#ztree1"), options, treeData)
    </script>
</body>
</html>

事件委托:

基于时间冒泡传播机制,一个容器中很多元素的相关行为都要绑定方法,此时没必要一个个获得元素一个个绑方法,只要给父元素容器相关事件行为绑方法就好了。不管容器中哪一个子元素事件触发,由于冒泡传播机制,父级容器的该事件都会触发,方法也会被执行。执行方法中,通过event.target事件源判断做不同的事情。几个作用:

第1个作用,性能好。

第2个,有些业务逻辑用事件委托处理更好。比如,点啥啥干啥除此之外统一干什么事,用事件委托处理。

第3个作用,元素是动态绑定的。不用事件委托,数据加载完页面渲染完获取到才绑定方法;用委托。用事件委托不用获取元素,给父元素绑接口。

基于递归完成数据动态绑定

样式

bindHTML

基于事件委托实现切换

浏览器调试:f10 逐过程;f11逐语句

调试:

  1. console.log

  2. debug

count累加

bindHTML: 没有children了就到底了,再返回的时候count--。返回上一级的时候count--。

获取所有em,循环事件绑定?

一个容器里面如果很多元素都要做事件绑定,那我不需要一个一个去绑,使用事件委托。

$level0.on('click',function (ev) {
    let target=ev.target,$target=$(target);
    if(target.tagName==='EM'){
        $target.toggleClass('open');
        $target.next('ul.level').toggle()
    }
})

封装为zTree插件

(function ($) {

    function zTree(data) {
        function bindHTML(result,level=1) {
            let liStr=''
            result.forEach(item=>{
                const {name,children,open}=item;
                liStr+=`<li>
                    <a class="title">${name}</a>
                    ${children?`<em class="icon ${open?'open':''}"></em>`:''}`
                if(children){
                    liStr+=`<ul class="level level${level}" style="display: ${open?'block':'none'}">${bindHTML(children,level+1)}</ul>`
                }
                liStr+=`</li>`
            })
            return liStr;
        }
        // 数据绑定
        $(this).html(bindHTML(data));
        // click事件
        $(this).on('click',function (ev) {
            let target=ev.target,$target=$(target);
            if(target.tagName==='EM'){
                $target.toggleClass('open');
                $target.next('ul.level').toggle()
            }
        })
    }

    $.fn.extend({
        zTree
    })

})(jQuery)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值