簡體   English   中英

如何將事件偵聽器回調設置為成員函數

[英]How to set an event listener callback to a member function

我正在圍繞畫布對象編寫一個小的面向對象的包裝器,我想為實際的函數成員設置一些按鈕回調,而不是全局范圍內的函數(通過這種方式,我可以將上下文對象稱為成員)。

function CanvasManager(canvasId) {
    this.canvas = document.getElementById(canvasId);    
    this.ctx = this.canvas.getContext('2d');    

    var imageLoader = document.getElementById('imageLoader');
    imageLoader.addEventListener('change', this.handleImage, false);

    var lineNumberField  = document.getElementById('linenumber');
    lineNumberField.addEventListener('change', this.onLineNumberChange, false);
}

function handleImage = function(e) {
    var reader = new FileReader();    
    var that = this;

    reader.onload = function(event){
        var img = new Image();

        img.onload = function(){
            that.canvas.width = img.width;
            that.canvas.height = img.height;
            that.ctx.drawImage(img,0,0);
        };

        img.src = event.target.result;
    };

    reader.readAsDataURL(e.target.files[0]);     
};

這是在html的內聯腳本中調用的:

<div id="canvas-container" style="display:none;">
    <canvas id="imageCanvas"></canvas>
</div>
    ...
<script lang="javascript">new CanvasManager('imageCanvas');</script>

這是行不通的,因為在handleImage回調中,“ this”不是引用CanvasManager實例,而是imageLoader實例,這令我非常困惑。

我在這里做錯了什么?

抱歉,您的評論-實際上,如果問題在第二種方法之內,則您對它的解釋不正確。

正如其他人所暗示的那樣,事件偵聽器將以window作為this對象來調用函數。 不用擔心,即使作為JS專家,我也認為這沒有任何意義。

雖然你可以簡單地把在關閉一切,把this變成一個恆定的var (即meself )我喜歡的是自定義調用該函數總是有特定的this參考。 您可以這樣做:

imageLoader.addEventListener('change', this.handleImage.bind(this), false);

bind()是一個相對較新的JavaScript函數,它為您提供了一個新方法,該方法代表原始方法,但使用特定的this上下文進行調用。 一些JavaScript庫具有與舊版瀏覽器兼容的等效項,例如Dojo的“ hitch”。 但是,由於您的代碼無論如何都涉及<canvas> ,因此您應該基本上可以兼容。

嘗試這個

function CanvasManager(canvasId) {
    this.canvas = document.getElementById(canvasId);    
    this.ctx = this.canvas.getContext('2d');    

    var imageLoader = document.getElementById('imageLoader');
    imageLoader.addEventListener('change', this.handleImage, false);

    var lineNumberField  = document.getElementById('linenumber');
    lineNumberField.addEventListener('change', this.onLineNumberChange, false);
    var self = this; // keep CanvasManager instance
    this.onLineNumberChange  = function(){
    };
    this.handleImage  = function(){
       console.log(self); // use CanvasManager instance
    }
}

看起來您的函數handleImage在您要使用的主函數(或類)之外。 我將更新代碼如下:

function CanvasManager(canvasId) {
    var me = this;

    me.canvas = document.getElementById(canvasId);    
    me.ctx = me.canvas.getContext('2d');    

    var imageLoader = document.getElementById('imageLoader');
    imageLoader.addEventListener('change', me.handleImage, false);

    var lineNumberField  = document.getElementById('linenumber');
    lineNumberField.addEventListener('change', me.onLineNumberChange, false);

    me.handleImage = function(e) {
        var reader = new FileReader();    

        reader.onload = function(event){
            var img = new Image();

            img.onload = function(){
                me.canvas.width = img.width;
                me.canvas.height = img.height;
                me.ctx.drawImage(img, 0, 0);
            };

            img.src = event.target.result;
        };

        reader.readAsDataURL(e.target.files[0]);     
    }
}

通過將handleImage移動到函數內部,它現在處於類的范圍內。 同樣通過在方法開始時使用me = this來始終可以訪問它的類實例,因為默認情況下,這將引用事件觸發它的對象。

暫無
暫無

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

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