更新或更改或删除/重置Javascript事件侦听器 [英] Update or Change or Remove/Reset Javascript event listener

查看:123
本文介绍了更新或更改或删除/重置Javascript事件侦听器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,所以我正在制作一个小的html5画布绘图库,我有一个小问题,这里是代码(小提琴):

  var drawr = {
init:function(canvas_id,canvasWidth,canvasHeight){// height&宽度是可选的
this.canvas_id = document.getElementById(canvas_id);
this.canvasWidth = canvasWidth;
this.canvasHeight = canvasHeight;
this.context = this.canvas_id.getContext('2d');

if(canvasWidth){
this.canvas_id.width = canvasWidth;
}

if(canvasHeight){
this.canvas_id.height = canvasHeight;
}

},

//魔术线绘制函数
ctx:function(a,b,x,y,dLineColor,dLineWidth){ // lineWidth& lineColor是可选的;默认值是1px& 'black'
this.context.lineJoin ='round';
this.context.beginPath();
this.context.moveTo(a,b);
this.context.lineTo(x,y);
this.context.closePath();
this.context.strokeStyle = dLineColor;
this.context.lineWidth = dLineWidth;
this.context.stroke();



//销毁事件处理程序以防止绘制
destroy:function(){
//销毁事件处理程序

},

draw:function(lineColor,lineWidth){
//创建绘图函数的一些实用程序以使用
var localPen = {};
var drawing = false;
var canvasPos = {
x:this.canvas_id.offsetLeft,
y:this.canvas_id.offsetTop
}

//发起事件处理程序
this.canvas_id.addEventListener('mousedown',addDraw,false);

函数addDraw(e){
drawing = true;
console.log(绘图);
localPen.x = e.pageX - canvasPos.x;
localPen.y = e.pageY - canvasPos.y;
};


this.canvas_id.addEventListener('mousemove',function(e){
var drawTo = {
x:e.pageX - canvasPos.x,
y:e.pageY - canvasPos.y
}
if(drawing){
drawr.ctx(localPen.x,localPen.y,drawTo.x,drawTo.y,lineColor, lineWidth);
}

localPen.x = drawTo.x;
localPen.y = drawTo.y;

});

this.canvas_id.addEventListener('mouseup',function(e){
drawing = false;
});

this.canvas_id.addEventListener('mouseleave',function(e){
drawing = false;
});
}

}

drawr.init('my_canvas');
drawr.draw('red',10);
drawr.draw('blue',5);

我在这里试图完成的是:当我调用 drawr .draw(); 第二个(或第三个等)为它覆盖前面的函数。我该怎么办呢?正如您在我的小提琴中所看到的,每个实例同时运行。



随意编辑,更新,删除,对我说错误代码等等。

解决方案

调用 addEventListener 将覆盖前一个,或者调用 removeEventListener 将删除一个侦听器,只有当处理程序为该事件类型指定的函数严格等于。一个匿名函数,即使在词汇上是相同的,也不等于在单独执行该方法期间创建的第二个匿名函数。



这里有一个想法:将你的处理程序定义为闭包中的单独函数,如下所示:

  obj = function(){
function handler(){/ *处理点击; this是元素* /}

return {
draw:function(){
this.elt.addEventListener('click',handler);
//绘制一堆东西
},

undraw:function(){
this.elt.removeEventListener('click',handler);
//解开一堆东西
}

};
}();

现在,由于处理程序始终严格相等本身, removeEventListener 将成功移除处理程序。或者,第二个 addEventListener 将不会执行任何操作(只保留当前的处理程序)。

然而, code> handler 无法访问该对象的;它将被事件的目标元素调用为 this 。为了将对象的添加到事件处理程序中,您可能会尝试

  this.elt.addEventListener('click',handler.bind(this)); 

但是这将无法实现您想要的,因为处理程序的值每次调用方法时,.bind(this)都不同,所以你将再次使用冗余事件处理程序,或 removeEventListener s如果你真的想在对象的这个处理程序中,并不能找出如何从事件中检索它,你可以在一些 init 函数中初始化一个处理程序的绑定版本:

  obj = {
处理程序:function(event){/ *处理单击; this是对象* /},

draw:function(){
this.elt.addEventListener('click',this.handler);
//绘制一堆东西
},

undraw:function(){
this.elt.removeEventListener('click',this.handler);
//取出一堆东西
},

init:function(){
this.handler = this.handler.bind(this);
返回此;
}
} .init();

由于 this.handler 总是相同的使用 EventListener

使用 p>解决这个问题的一个更好的方法是传递给 addEventListener ,而不是一个函数,一个带有 EventListener 接口,它是实现特殊命名的 handleEvent 方法,它可以是'this'对象本身,所以你可以这样做:

  obj = {
handleEvent:function(event){
//this是对象
if(event.type ==='click'){
// do stuff
}
},
draw:function(){
this.elt.addEventListener('click',this);
},
undraw:function(){
this.elt.removeEventListener('click',this);
}
};

注意这个传递给的addEventListener 。换句话说,我们通过实现 handleEvent 来传递对象本身,作为 EventListener 的一个实例$ C>。 handleEvent 是一个完整的对象方法,因此可以完全访问它的所有方法和属性,并且因为 this 与自身相同,添加,添加和删除行为可以根据需要使用。

我没有看到这个方法被使用得非常多,但它可以使事件处理更加流畅,特别是如果你在它周围添加一些糖,比如安排个别方法来处理每一个事件类型:

$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ [event.type](事件); //调度到事件名称为
}的方法,
点击:function(event){
//句柄点击; this是obj
},

draw:function(){
this.elt.addEventListener('click',this);
},
undraw:function(){
this.elt.removeEventListener('click',this);
}
};


Ok, so I'm working on a small html5 canvas drawing library and I'm having a slight problem, here's the code (fiddle below):

var drawr = {
init: function (canvas_id, canvasWidth, canvasHeight) { //height & width are optional
    this.canvas_id = document.getElementById(canvas_id);
    this.canvasWidth = canvasWidth;
    this.canvasHeight = canvasHeight;
    this.context = this.canvas_id.getContext('2d');

    if (canvasWidth) {
        this.canvas_id.width = canvasWidth;
    }

    if (canvasHeight) {
        this.canvas_id.height = canvasHeight;
    }

},

//magic line drawing function
ctx: function (a, b, x, y, dLineColor, dLineWidth) { //lineWidth & lineColor are optional; defaults are 1px & 'black'
    this.context.lineJoin = 'round';
    this.context.beginPath();
    this.context.moveTo(a, b);
    this.context.lineTo(x, y);
    this.context.closePath();
    this.context.strokeStyle = dLineColor;
    this.context.lineWidth = dLineWidth;
    this.context.stroke();

},

//destroy event handlers to prevent drawing
destroy: function () {
    //destroy event handlers

},

draw: function (lineColor, lineWidth) {
    //create some utilities for draw function to use
    var localPen = {};
    var drawing = false;
    var canvasPos = {
        x: this.canvas_id.offsetLeft,
        y: this.canvas_id.offsetTop
    }

    //initiate event handlers
    this.canvas_id.addEventListener('mousedown', addDraw, false);

    function addDraw(e) {
        drawing = true;
        console.log(drawing);
        localPen.x = e.pageX - canvasPos.x;
        localPen.y = e.pageY - canvasPos.y;
    };


    this.canvas_id.addEventListener('mousemove', function (e) {
        var drawTo = {
            x: e.pageX - canvasPos.x,
            y: e.pageY - canvasPos.y
        }
        if (drawing) {
            drawr.ctx(localPen.x, localPen.y, drawTo.x, drawTo.y, lineColor, lineWidth);
        }

        localPen.x = drawTo.x;
        localPen.y = drawTo.y;

    });

    this.canvas_id.addEventListener('mouseup', function (e) {
        drawing = false;
    });

    this.canvas_id.addEventListener('mouseleave', function (e) {
        drawing = false;
    });
    }

}

    drawr.init('my_canvas');
    drawr.draw('red', 10);
    drawr.draw('blue', 5);

What I'm trying to accomplish here is this: when I call drawr.draw(); a second (or third, etc) for it to override the previous function. How should I go about this? As you can see in my fiddle each instance simultaneously runs.

Feel free to edit, update, delete, yell at me for bad code, etc.

解决方案

A call to addEventListener will override the previous one, or a call to removeEventListener will remove a listener, only when the handler functions specified for that event type are strictly equal. A anonymous function, even if lexically identical, will not be equal to a second anonymous function created during a separate execution of the method.

Here's one idea: define your handler as a separate function in a closure, as follows:

obj = function() {
    function handler() { /* handle the click; "this" is the element */ }

    return {
        draw: function() {
            this.elt.addEventListener('click', handler);
            //draw a bunch of stuff
        },

        undraw: function() {
            this.elt.removeEventListener('click', handler);
            //undraw a bunch of stuff
        }

    };
}();

Now, since handler is always strictly equal to itself, the removeEventListener will successfully remove the handler. Or, a second addEventListener will not do anything (just leave the current handler in place).

However, handler has no access to the this of the object; it will be called with the event's target element as its this. In order to get the object's this into the event handler, you may be tempted to try

this.elt.addEventListener('click', handler.bind(this));

but this will fail to accomplish what you want, because the value of handler.bind(this) is different each time the method is invoked, so you will again end up with redundant event handlers, or removeEventListeners which do not work.

If you really want the object's this in the handler, and can't figure out how to retrieve it from the event, you could initialize a bound version of handler in some init function:

obj = {
    handler: function(event) { /* handle the click; "this" is the object */ },

    draw: function() {
        this.elt.addEventListener('click', this.handler);
        //draw a bunch of stuff
    },

    undraw: function() {
        this.elt.removeEventListener('click', this.handler);
        //undraw a bunch of stuff
    },

    init: function() {
        this.handler = this.handler.bind(this);
        return this;
    }
}.init();

Since this.handler is always identical to itself, this works as expected.

Using EventListener

A somewhat more elegant way to solve this problem is to pass to addEventListener, instead of a function, an object with the EventListener interface, which is any object that implements the specially-named handleEvent method, which could be the 'this' object itself, so you can do:

obj = {
    handleEvent: function(event) {
        // "this" is the  object
        if (event.type === 'click') {
            // do stuff
        }
    },
    draw: function() {
        this.elt.addEventListener('click', this);
    },
    undraw: function() {
        this.elt.removeEventListener('click', this);
    }
};

Note the this being passed to addEventListener. In other words, we are passing the object itself, in its incarnation as an instance of EventListener, by virtue of its having implemented handleEvent. handleEvent is a full-fledged method of the object and as such has full access to all its methods and properties, and because this is identical to itself, the adding, adding again, and removing behavior works as you want.

I don't see this approach used very much, but it can make event handling more streamlined, especially if you add some sugar around it, such as arranging for individual methods to handle each event type:

obj = {
    handleEvent: function(event) {
        return this[event.type](event); // dispatch to method with name of event
    },
    click: function(event) {
        // handle click; "this" is obj
    },

    draw: function() { 
        this.elt.addEventListener('click', this); 
    },
    undraw: function() {
        this.elt.removeEventListener('click', this);
    }
};

这篇关于更新或更改或删除/重置Javascript事件侦听器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆