您的当前位置:首页正文

【开发备忘录】event.currentTarget 异步为null

2024-11-07 来源:个人技术集锦

背景

el-table实现行单击行双击事件,但是发现每次行双击都会触发2次行单击事件。于是,在事件中添加防抖机制(setTimeout异步实现)

问题

加入防抖机制后,代码报错如下:

Uncaught TypeError: Cannot read properties of null (reading 'hasAttribute')
    at getAttributeValue (clipboard.js?b311:299)
    at Clipboard.defaultAction (clipboard.js?b311:220)
    at Clipboard.onClick (clipboard.js?b311:203)
    at handleClipboard (VM61884 clipFunc.js:24)
    at eval (DetailList.vue?0edb:126)

解决

逗逼博主无奈求助度娘,却迟迟找不到对的解决方法,被导师逼着不停想解决方法QAQ:
el-table 行单击和行双击冲突Cannot read properties of nulljs 双击不触发单击setTimeout event 消失setTimeout的坑event.currentTarget 文档event.currentTarget生命周期


异步操作setTimeoutevent.currentTarget会置空的问题,需要单独保存它的值

const tmp = e.currentTarget // ! 保存e.currentTarget

深层原因

导师询问原因,又开始一轮疯狂检索:
event.currentTarget 文档event.currentTarget生命周期
最终发现原因:event产生的时候会注册currentTarget,等该event绑定的主线程中的事件顺序执行结束后,立刻会将它置为null。所以只要在顺序事件执行结束前,单独保存event.currentTarget就可以了。

测试代码:

function func (e) {
    console.log(1, e.currentTarget===null)   // false
    sleep(2000)
    console.log(2, e.currentTarget===null)   // false
    
	const tmp = e.currentTarget // ! 保存e.currentTarget
    timeOut= setTimeout(function () {
        console.log('单击');
      
        console.log(3, e.currentTarget===null) // true
        console.log('tmp', tmp===null)         // false
    }, time)
    console.log(4, e.currentTarget===null)     // false
}
function sleep(d){ 
    let t = Date.now();
    while(Date.now() - t <= d); 
}
1     false // 同步函数 start
2     false // sleep(2000)
4     false // 同步函数end
'单击'
3     true  // 延迟器的异步输出
'tmp' false // 单独保存

Event 简单示例

class Event {
    constructor(type, target) {
        this.type = type
        this.target = target
        this.currentTarget = null
    }

    static fire(type, target, currentTarget) {
        const event = new Event(type, target)
        // 事件触发时, 将 currentTarget 绑定到事件对象中
        event.currentTarget = currentTarget
        // 执行监听的函数
        event.currentTarget.eventListener[type].forEach(fn => fn(event))
        // 事件处理结束后,再将 currentTarget 移除
        event.currentTarget = null
    }
}

Top