JavaScript(ES6)类没有';不要让元素拖拉

JavaScript(ES6)类没有';不要让元素拖拉,javascript,ecmascript-6,es6-class,Javascript,Ecmascript 6,Es6 Class,我正在尝试使用类将函数转换为ES6。以下代码作为一个函数,定义元素以使其可拖动: 'use strict'; var Drag = function(el) { var elem = document.querySelector(el); this.move =(e)=> { elem.style = 'position:absolute;'+ 'top:'+e.clientY+'px;'+

我正在尝试使用类将函数转换为ES6。以下代码作为一个函数,定义元素以使其可拖动:

'use strict';

var Drag = function(el) {

    var elem = document.querySelector(el);

    this.move =(e)=> {
        elem.style = 
            'position:absolute;'+
            'top:'+e.clientY+'px;'+
            'left:'+e.clientX+'px;'+
            'margin-left:-25px;'+
            'margin-top:-10px';
    }

    this.up =()=> { window.removeEventListener('mousemove', this.move, true); }

    this.down =()=> { window.addEventListener('mousemove', this.move, true); }

    this.events =()=> {
        elem.addEventListener('mousedown', this.down, false);
        window.addEventListener('mouseup', this.up, false);
    }

    return this.events();
};

window.onLoad = (()=> {
    var drag = new Drag('#dragme');
})();
上面的代码正在运行。但是,下面的代码甚至没有在控制台中显示错误。这就像它不会执行,但它部分执行。我觉得方法
up()
down()
可能会导致问题。因为某种原因它不会开火

'use strict';

class Drag {

    constructor(el) {
        this.el = document.querySelector(el);
        this.events();
    }

    move(e) {
        this.el.style = 
            'position:absolute;'+
            'top:'+e.clientY+'px;'+
            'left:'+e.clientX+'px;'+
            'margin-left:-25px;'+
            'margin-top:-10px';
    }

    up() { window.removeEventListener('mousemove', this.move, true); }

    down() { window.addEventListener('mousemove', this.move, true); }

    events() {
        this.el.addEventListener('mousedown', this.down, false);
        window.addEventListener('mouseup', this.up, false);
    }

}

window.onLoad = (()=> {
    const drag = new Drag('#dragme');
})();

我做错了什么?提前感谢。

在第一个示例中,构造函数将每个方法的一个新实例分配给
this
。您还使用了箭头函数,它捕获
上下文

在第二种情况下,类的所有实例共享相同的方法

这有两个问题:

  • 它们的
    this
    上下文是不固定的,因此当
    window
    调用
    this.move
    作为mousemove处理程序时,
    move
    方法中的
    this
    不再引用
    Drag
    的实例。它指的是
    窗口

  • 如果这真的执行过(尽管不会,因为原因1)

    window.removeEventListener('mousemove',this.move,true)

  • 它将删除类的所有实例共享的
    this.move
    ,而不仅仅是当前的
    Drag
    move
    方法

    解决方案:

    就像您在第一个示例中所做的那样,将方法附加到构造函数中。另一方面,这几乎违背了使用
    类的目的:

    class Drag {
    
        constructor(el) {
            this.el = document.querySelector(el);
            this.move = (e) => ....;
            this.up = () => .....;
            // etc...
            this.events();
        }
    
        events() {
            this.el.addEventListener('mousedown', this.down, false);
            window.addEventListener('mouseup', this.up, false);
        }
    
    }
    
    旁注:我倾向于通过根本不使用
    这个
    来消除所有的
    这个
    混乱。毕竟,代码中的
    new Drag()
    实际上并没有创建任何可以与之高效交互的内容:

    function drag(el) {
        var elem = document.querySelector(el);
    
        function move(e) {
            elem.style = 
                'position:absolute;'+
                'top:'+e.clientY+'px;'+
                'left:'+e.clientX+'px;'+
                'margin-left:-25px;'+
                'margin-top:-10px';
        }
    
        function up() { window.removeEventListener('mousemove', move, true); }
    
        function down() { window.addEventListener('mousemove', move, true); }
    
        function events() {
            elem.addEventListener('mousedown', down, false);
            window.addEventListener('mouseup', up, false);
        }
    };
    
    window.onLoad = (()=> {
        drag('#dragme');
    })();
    

    在第一个示例中,构造函数将每个方法的新实例分配给
    this
    。您还使用了箭头函数,它捕获
    上下文

    在第二种情况下,类的所有实例共享相同的方法

    这有两个问题:

  • 它们的
    this
    上下文是不固定的,因此当
    window
    调用
    this.move
    作为mousemove处理程序时,
    move
    方法中的
    this
    不再引用
    Drag
    的实例。它指的是
    窗口

  • 如果这真的执行过(尽管不会,因为原因1)

    window.removeEventListener('mousemove',this.move,true)

  • 它将删除类的所有实例共享的
    this.move
    ,而不仅仅是当前的
    Drag
    move
    方法

    解决方案:

    就像您在第一个示例中所做的那样,将方法附加到构造函数中。另一方面,这几乎违背了使用
    类的目的:

    class Drag {
    
        constructor(el) {
            this.el = document.querySelector(el);
            this.move = (e) => ....;
            this.up = () => .....;
            // etc...
            this.events();
        }
    
        events() {
            this.el.addEventListener('mousedown', this.down, false);
            window.addEventListener('mouseup', this.up, false);
        }
    
    }
    
    旁注:我倾向于通过根本不使用
    这个
    来消除所有的
    这个
    混乱。毕竟,代码中的
    new Drag()
    实际上并没有创建任何可以与之高效交互的内容:

    function drag(el) {
        var elem = document.querySelector(el);
    
        function move(e) {
            elem.style = 
                'position:absolute;'+
                'top:'+e.clientY+'px;'+
                'left:'+e.clientX+'px;'+
                'margin-left:-25px;'+
                'margin-top:-10px';
        }
    
        function up() { window.removeEventListener('mousemove', move, true); }
    
        function down() { window.addEventListener('mousemove', move, true); }
    
        function events() {
            elem.addEventListener('mousedown', down, false);
            window.addEventListener('mouseup', up, false);
        }
    };
    
    window.onLoad = (()=> {
        drag('#dragme');
    })();
    

    绑定属于事件的方法并使用
    ,否则将无法定义上下文

    move = (e) => {
      this.el.style = ...;
    }
    

    绑定属于事件的方法并使用
    ,否则将无法定义上下文

    move = (e) => {
      this.el.style = ...;
    }
    
    另一个解决方案(请注意,我更喜欢JLRishe中的解决方案!)是显式地提供
    这个
    变量是什么

    'use strict';
    class Drag {
    
        constructor(el) {
            this.el = document.querySelector(el);
            this.events();
        }
    
        move(e) {
            this.el.style = 
                'position:absolute;'+
                'top:'+e.clientY+'px;'+
                'left:'+e.clientX+'px;'+
                'margin-left:-25px;'+
                'margin-top:-10px';
        }
    
        up() { window.removeEventListener('mousemove', this.eventHandler, true); }
    
        down() { 
            this.eventHandler = this.move.bind(this)
            window.addEventListener('mousemove', this.eventHandler , true); 
        }
    
        events() {
            this.el.addEventListener('mousedown', this.down.bind(this), false);
            window.addEventListener('mouseup', this.up.bind(this), false);
        }
    
    }
    
    window.onLoad = (()=> {
        const drag = new Drag('#dragme');
    })();`
    
    另一个解决方案(请注意,我更喜欢JLRishe中的解决方案!)是显式地提供
    这个
    变量是什么

    'use strict';
    class Drag {
    
        constructor(el) {
            this.el = document.querySelector(el);
            this.events();
        }
    
        move(e) {
            this.el.style = 
                'position:absolute;'+
                'top:'+e.clientY+'px;'+
                'left:'+e.clientX+'px;'+
                'margin-left:-25px;'+
                'margin-top:-10px';
        }
    
        up() { window.removeEventListener('mousemove', this.eventHandler, true); }
    
        down() { 
            this.eventHandler = this.move.bind(this)
            window.addEventListener('mousemove', this.eventHandler , true); 
        }
    
        events() {
            this.el.addEventListener('mousedown', this.down.bind(this), false);
            window.addEventListener('mouseup', this.up.bind(this), false);
        }
    
    }
    
    window.onLoad = (()=> {
        const drag = new Drag('#dragme');
    })();`
    

    window.addEventListener('mousedown',this.down.bind(this),false);等否则
    this`对象将是触发事件的元素。如果要使用箭头函数,您仍然必须将它们放入
    构造函数中
    ,就像原始
    函数中一样。
    window.addEventListener('mousedown',this.down.bind(this),false);等否则
    this`对象将是触发事件的元素。如果要使用箭头函数,您仍然必须将它们放入
    构造函数
    中,就像原始
    函数
    中一样。非常感谢,这样做了。我知道这门课有点多余。我只是想了解函数/类的区别,因为我来自PHP,并试图找到相似之处,以便更好地与之相处,哈哈。再次感谢你的解释。非常感谢,就这样。我知道这门课有点多余。我只是想了解函数/类的区别,因为我来自PHP,并试图找到相似之处,以便更好地与之相处,哈哈。再次感谢你的解释。这很好地解决了问题。不过我只能接受一个答案,我会投票支持你的工作,谢谢你。这就很好了。不过我只能接受一个答案,我会投票支持你的工作,谢谢。