簡體   English   中英

更新或更改或刪除/重置Javascript事件偵聽器

[英]Update or Change or Remove/Reset Javascript event listener

好的,所以我正在開發一個小的html5 canvas繪圖庫,但是我遇到了一個小問題,這是代碼(下面的小提琴):

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);

我要在這里完成的工作是:當我調用drawr.draw(); 第二個(或第三個,等等)以覆蓋先前的功能。 我應該怎么做? 正如您在我的小提琴中看到的那樣,每個實例同時運行。

隨意編輯,更新,刪除,對我大喊不好的代碼,等等。

僅當為該事件類型指定的處理函數嚴格相等時,對addEventListener的調用將覆蓋前一個,或對removeEventListener的調用將刪除偵聽removeEventListener 匿名函數即使在詞法上相同,也將不等於在單獨執行該方法期間創建的第二個匿名函數。

這是一個想法:將您的處理程序定義為閉包中的單獨函數,如下所示:

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
        }

    };
}();

現在,由於handler始終嚴格等於其自身,因此removeEventListener將成功刪除處理程序。 或者,第二個addEventListener將不執行任何操作(只需將當前處理程序留在原處)。

但是, handler無法訪問該對象的this 它將使用事件的目標元素作為其this進行調用。 為了得到對象的this到這個事件處理,你可能會嘗試

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

但這將無法完成您想要的操作,因為每次調用該方法時, handler.bind(this)的值都不同,因此您將再次獲得多余的事件處理程序或removeEventListener ,它們均無效。

如果你真的想對象的this在處理程序,並不能弄清楚如何從事件檢索它,你可以初始化的綁定版本handler在一些init函數:

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();

由於this.handler始終與其自身相同,因此可以正常工作。

使用EventListener

解決此問題的一種更優雅的方法是將帶有EventListener接口的對象傳遞給addEventListener而不是函數,該對象是實現特殊命名的handleEvent方法的任何對象,該對象可以是'this'對象本身,因此,您可以執行以下操作:

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);
    }
};

請注意, this已傳遞給addEventListener 換句話說,由於對象本身已實現handleEvent ,因此以對象的形式將其本身作為EventListener的實例傳遞。 handleEvent是對象的完整方法,因此可以完全訪問其所有方法和屬性,並且由於this與自身完全相同,因此添加,再次添加和刪除行為都可以根據需要進行。

我看不到這種方法使用得太多,但是它可以使事件處理更加簡化,尤其是如果在它周圍添加一些糖,例如安排單獨的方法來處理每種事件類型:

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);
    }
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM