【问题标题】:Why I could not add mousemove event after mousedown in prototype?为什么我无法在原型中的 mousedown 之后添加 mousemove 事件?
【发布时间】:2010-10-23 19:36:35
【问题描述】:

我会将我以前的 js 代码转移到更多的 OOP 风格。这是代码。

function addEvent( obj, type, fn ) {
  if ( obj.attachEvent ) {
    obj['e'+type+fn] = fn;
    obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
    obj.attachEvent( 'on'+type, obj[type+fn] );
  } else
    obj.addEventListener( type, fn, false );
}

function test() {

}

test.prototype = {
    init: function () {

        addEvent(document, 'mousedown', this.displaydown);

    },

    displaydown : function(e){
        document.getElementById('mydiv').innerHTML = "down";
        addEvent(document, 'mousemove', this.displaymove);
    },

    displaymove : function(e){
        document.getElementById('mydiv').innerHTML = "move";
    }
}

var test0 = new test();

test0.init()

我无法在鼠标按下后添加 mousemove 事件

addEvent(document, 'mousemove', this.displaymove);

但是如果我写像这样的内联样式

addEvent(document, 'mousemove', function(e){
   document.getElementById('mydiv').innerHTML = "move";
});

没关系。看起来这两个代码做同样的事情。为什么有区别?谢谢!


编辑,

经过2个晚上的努力,我终于解决了这个问题。感谢 johnvey 的启发。

this 关键字出现错误。如果是对象,this 指的是窗口而不是对象本身。解决方法是我在开头定义了全局参数me (me = this)。现在好了。

【问题讨论】:

    标签: javascript object events mousemove


    【解决方案1】:

    这是一个经典的 Javascript 绊脚石,与“this”键在闭包中的作用域有关。举例说明:

    redPrinter = function() {
        this.X = 'red';
        return function() {
            return this.X;
        }
    }
    
    main = function() {
        this.X = 'blue';
        var myRedPrinter = new redPrinter();
        alert("Red printer returned: " + myRedPrinter());
    }
    
    main();
    

    此代码将打印出来:

    Red printer returned: blue
    

    因为'this'在行中的作用域:

    return this.X
    

    在调用时实际上与 main() 对象绑定。

    一般有两种方法可以解决这个问题:

    1) 避免在函数闭包中使用“this”关键字。要以这种方式修复您的代码,我只需将所有事件绑定收集在一个地方而不是级联它们,从而从“displaydown()”和“displaymove()”中删除“this”引用:

    test.prototype = {
        init: function () {
            addEvent(document, 'mousedown', this.displaydown);
            addEvent(document, 'mousemove', this.displaymove);
        },
    
        displaydown : function(e){
            document.getElementById('mydiv').innerHTML = "down";
        },
    
        displaymove : function(e){
            document.getElementById('mydiv').innerHTML = "move";
        }
    }
    

    2) 在定义时使用函数柯里化绑定作用域。我已经从 Prototype 库中提取了 bind() 方法来说明:

    // declare the global bind() method for all functions
    Function.prototype.bind = function(obj) {
        var method = this,
        temp = function() {
            return method.apply(obj, arguments);
        };
        return temp;
    } 
    
    test.prototype = {
        init: function () {
            addEvent(document, 'mousedown', this.displaydown);
        },
    
        displaydown : function(e){
            document.getElementById('mydiv').innerHTML = "down";
    
            // note that we bind the method object here
            addEvent(document, 'mousemove', this.displaymove.bind(this));
        },
    
        displaymove : function(e){
            document.getElementById('mydiv').innerHTML = "move";
        }
    }
    

    这里的重要变化是:

    this.displaymove.bind(this)
    

    这基本上是说,“当你调用 displaymove() 时,将关键字 'this' 重新作用于原始作用域上下文而不是当前的 Event 对象。

    【讨论】:

    • 嗨,约翰维,谢谢!我想我需要做第二种方法。但我无法绑定()。在这一步出现错误。我正在使用 IE.6。是这个原因吗?
    • IE6 应该不是问题。你得到的错误是什么?作为一个更大的问题,你想要做什么?从另一个事件处理程序内部调用 addEvent() 并不好,因为您最终会一遍又一遍地附加相同的处理程序。
    • johnvey,我终于在您的代码中发现了错误。 addEvent(document, 'mousedown', this.displaydown);也应该绑定。或者在 mousedown 范围内的 this 是 window.我刚刚研究了一个易于加载的滑块。 pagecolumn.com/webparts/sliders.htm
    猜你喜欢
    • 2017-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多