You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

添加EventListener时出现Uncaught ReferenceError问题排查

区块拖拽功能实现中的监听器引用错误问题

我尝试用类独立实现区块拖拽功能,添加EventListener时出现异常。点击label元素后控制台抛出错误:

Uncaught ReferenceError: listener is not defined
at HTMLDocument. (main.js:31:63)
(anonymous) @ main.js:31

如果在类外部对已存在DOM元素执行相同逻辑代码能正常运行;改成具名函数形式后拖拽功能生效,但移除监听器时还是报同样的错。

原实现代码

class Form {
    constructor() {
        //pass
    }
    DOMGenerator(elemClass) {
        const element = document.createElement('div');
        element.classList.add(elemClass);
        return element;
    }
    Draw() {
        const form = this.DOMGenerator('window'),
            label = this.DOMGenerator('window_label'),
            controls = this.DOMGenerator('window_controls'),
            close = this.DOMGenerator('close'),
            minimize = this.DOMGenerator('minimize'),
            maximize = this.DOMGenerator('maximize')

            label.addEventListener('mousedown', event => {
                const offsetX = event.offsetX;
                const offsetY = event.offsetY;
        
                document.addEventListener('mousemove', listener = event => {
                    let pageX = event.pageX;
                    let pageY = event.pageY;
            
                    form.style.left = `${pageX - offsetX}px`;
                    form.style.top = `${pageY - offsetY}px`;
                })
        
                document.addEventListener('mouseup', () => {
                    document.removeEventListener('mousemove', listener, false);
                })
            })
        
            controls.append(close, minimize, maximize);
            label.append(controls);
            form.append(label);
            document.body.append(form);
    }
}

new Form().Draw();

修改后的具名函数代码

document.addEventListener('mousemove', function listener(event) {
    let pageX = event.pageX;
    let pageY = event.pageY;

    form.style.left = `${pageX - offsetX}px`;
    form.style.top = `${pageY - offsetY}px`;
})

问题原因及解决方法

  1. 错误根源

    • 第一种写法中,listener = event => {...} 试图赋值给未声明的变量,类内部默认运行在严格模式下,不会自动创建全局变量,导致mouseup回调执行时找不到listener。
    • 修改后的具名函数写法里,function listener是函数表达式的内部名称,仅在函数自身范围内可见,外部的mouseup回调无法访问这个引用,因此removeEventListener无法匹配到对应的监听器。
  2. 正确实现方案
    在mousedown回调内部提前声明拖拽处理函数,让mouseup回调能直接访问到这个函数引用:

    label.addEventListener('mousedown', event => {
        const offsetX = event.offsetX;
        const offsetY = event.offsetY;
    
        // 提前定义拖拽处理函数
        const dragHandler = event => {
            let pageX = event.pageX;
            let pageY = event.pageY;
            form.style.left = `${pageX - offsetX}px`;
            form.style.top = `${pageY - offsetY}px`;
        }
    
        document.addEventListener('mousemove', dragHandler);
        document.addEventListener('mouseup', () => {
            document.removeEventListener('mousemove', dragHandler);
        })
    })
    
  3. 额外提示

    • 确保给form元素添加position: absolute或position: fixed样式,否则left和top属性不会生效。

内容的提问来源于stack exchange,提问作者ExisterPro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 22:30:52