element ui treetable 触发展开事件_DOM事件和事件委托

一、DOM事件

DOM事件分为捕获阶段,事件阶段和冒泡阶段。

  • 捕获:当用户点击按钮,浏览器会从 window 从上向下遍历至用户点击的按钮,逐个触发事件处理函数。
  • 冒泡:浏览器从用户点击的按钮从下往上遍历至 window,逐个触发事件处理函数。
  • W3C 事件模型/事件机制:对每个事件先捕获再冒泡

9302f44c6216cfd07f53a2c091cd84bd.png

我们可以看到,其执行顺序为,捕获 => 目标 => 冒泡

所以,如果用户点击了td元素,并且,td元素的祖先元素拥有监听函数,那么其祖先元素也算被点击了。

但是,如果被点击的元素没有父元素,且他被用户点击了,那么,冒泡与捕获的顺序取决于JS代码的顺序

DOM事件拥有捕获和冒泡阶段,那么监听函数会不会被调用两次呢?

答案是不会,W3C 制定了一个标准

xxx.addEventListener('eventType',fn,bool)

若bool为falsy值或不传(0,'',NaN,undefined,null),那么,绑定为冒泡,若为true则为捕获。

4845682ac33e87da9a04ac4420a3fc53.png

需要特别注意的是,如果我们需要延迟触发事件

6260fc17e49eff642750c10c63bf651f.png

那么直接监听,是监听不到事件的,因为1s后,点击事件已经结束了(currentTarget为null),所以我们需要将点击事件记录下来。

e3decbeb4a2307df35d468ce7e387212.png

二、target VS currentTarget

target 与 currentTarget 的区别在于,e.target是用户操作的元素e.currentTarget是程序员监听的元素。

例如 div>span{文字},那么用户点击文字

span就是target

div就是currentEvent

三、冒泡的取消

通常情况下,我们可以通过stopPropagation阻止冒泡(捕获无法被取消)。

(例如当我们点击一个内部标签时,不想触发外部标签的事件,可以使用这种方法)

166af99f2109a673decc6d86e1711c05.png

67f12223307679fd04453101aac53680.png

例如,scroll 事件就无法取消冒泡,所以我们只能通过其他办法取消,例如使滚动条的宽度为0,阻止滚轮的默认事件,阻止移动端touchstart的默认事件。

cf53019b3bc029ea989f2436de2b46b4.png
x.addEventListener('wheel', (e)=>{
  console.log(2)
  e.preventDefault()
})

dom事件类型有很多,具体我们可以参考MDN

四、自定义事件

button1.addEventLsitener('click',()=>{
    const event = new CustomEvent('name',{
        {'detail':{name:'wang',age:'18'}},
        bubbles:true,
        cancelable:true
    })
    button1.dispatchEvent(event)
})

五、事件委托

事件委托就是监听祖先元素,判断被点击的元素是否是我们想监听的元素,若是,则执行函数。 其优点是节省内存以及可以监听动态生成的元素

function on(eventType,element,selector,fn){
    if(!(element instanceof Element)){
        element = document.querySelector(element)
    }
    
    element.addEventListener(eventType,(e)=>{
        t = e.target
        if (t.tagName.toLowercase() === selector){
            fn(e)
        }
    })
}

如果我们将事件委托函数封装成以上形式,我们会发现一个问题,当用户点击时,target不一定是我们监听的元素。

所以,我们需要使用递归,来寻找target的祖先元素,直到祖先元素是element为止。

function on(eventType,element,selector,fn){
    if (!(element instanceof Element)){
        element = document.querySelector(element)
    }
    
    element.addEventListener(eventType,(e)=>{
        let t = e.target
        while(t.tagName.toLowercase() !== selector){
            if(t === element){
                t = null
                break
            }
            t = t.parentNode
        }
        t && fn.call(t,e,t)
    })
    return element
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值