簡體   English   中英

當我在事件處理程序中引用對象的參數時,即使將其設置為對象,該參數也始終為null

[英]When I reference a parameter of an object inside of an event handler, the parameter is always null even when it's set to an object

這是我的第一個堆棧溢出問題,因為我通常在谷歌搜索時會找到答案,所以請耐心等待...

我正在從事一個涉及對畫布元素進行大量操作的項目。 為此,我已經導入並使用了jQuery和jCanvas。 我也在用ECMAScript 6編寫代碼。為了簡化日志記錄方法,我使用了日志級別(因此使用“ log.debug”和“ log.info”等,而不是“ console.log”)。

當前,我的問題是事件處理程序與我用來存儲有關每個畫布的數據的對象有一些奇怪的交互。 基本上,在我的mousedown和mousemove處理程序中,我使用getCanvasData函數來檢索該特定畫布的數據對象,顯然我已成功檢索了該對象,但是當我訪問“ draged”參數時,它始終為null。 在代碼的其他部分,我成功地將該值更改為對象,但是無論何時事件處理程序訪問它,該值始終為null。 我通過為該屬性創建一個getter和setter來測試它是否真的為空,該屬性會在狀態更改時打印出其狀態(我在最后提供了該代碼段,它代替了getCanvasData函數中的“ data”賦值)。

如果您希望以其當前形式查看完整的代碼,則可以查看我當前托管它的項目 這是一個實時版本,這意味着它與我的工作環境同步。 當我在家中修改某些內容時,它將更新網站(因此,如果您來自未來,它可能會宕機或完全不同)。

在網站上,當您生成電線/連接器的一端(單擊輸入或輸出之一)時,移動處理程序應該負責移動電線/連接器的一端。 由於處理程序無法檢索“拖動”,因此導線將永遠不會跟隨鼠標。 但是,當您單擊另一個輸入/輸出時(請記住,輸入僅連接到輸出,反之亦然),它將連接它們之間的連線-通過訪問“拖動”屬性(“拖動”為參考導線本身)並對其執行操作。 由於您可以連接電線,這意味着在處理程序外部(而不是在處理程序內部)成功引用了“拖動”。

getCanvasData()函數:

var canvasData = []; // (among other declarations)

function getCanvasData(canvas) {
    var data, i, tmp;
    // Retrieve the stored data
    for (i = 0; i < canvasData.length; i++) {
        tmp = canvasData[i];
        if (canvas === tmp.canvas) {
            // We got the data for our canvas!
            data = tmp;
            // We no longer need to go through the rest of the list, let's break out of the loop
            break;
        }
    }
    // Check if we got anything back
    if (!data) {
        // No data for this canvas is stored yet. We need to initialize it!
        log.info("New canvas data set is being created. Index: " + canvasData.length);
        data = {
            canvas: canvas, // The canvas this data belongs to
            gates: [],      // An array of all the logic gates on the canvas
            wires: [],      // An array of all the wires on the canvas
            spawners: [],   // An array of all the spawners on the canvas
            dragged: null,  // Currently dragged wire which should follow our mouse
            gateWidth: GATE_WIDTH,  // Width of all logic gates on this canvas
            gateHeight: GATE_HEIGHT // Height of all logic gates on this canvas
        };
        // Store the data in our storage.
        canvasData.push(data);
    }
    return data;
}

我將部分代碼分配給特定類的所有畫布不同的處理程序:

var canvasList = $('.logicExercise'), canvas;

/* some code */

// Initialize each canvas
canvasList.each(function (i, obj) {
    canvas = $(this);
    // Initialize the data stored for the canvas
    getCanvasData(canvas);
    // Draw the UI for the canvas
    drawUI(canvas);
    // Assign mouse handlers (for spawning new wires)
    canvas.mousemove(function(event) {
        mouseMoveHandler(event, canvas);
    });
    canvas.mousedown(function(event) {
        mouseDownHandler(event, canvas);
    });
    // Prevent right-click from firing up the context menu when over the canvas
    canvas.bind('contextmenu', function(e){
        e.preventDefault();
        return false;
    });
});

mousedown和mousemove處理程序:

function mouseMoveHandler(event, canvas) {
    var x = event.pageX - canvas.offset().left,
        y = event.pageY - canvas.offset().top,
        data = getCanvasData(canvas);
    if (data.dragged) {    // <--- ALWAYS NULL, AND THEREFORE FAILS
        if (data.dragged.inputs[0].type) {
            data.dragged.outputs[0].x = x;
            data.dragged.outputs[0].y = y;
            data.dragged.updateCoords();
        } else {
            data.dragged.inputs[0].x = x;
            data.dragged.inputs[0].y = y;
            data.dragged.updateCoords();
        }
    }
}

function mouseDownHandler(event, canvas) {
    var data = getCanvasData(canvas);
    if (event.which === 3) {
        // Right click detected!
        if (data.dragged) {    // <--- ALWAYS NULL, AND THEREFORE FAILS
            // We are dragging something! Right click means we need to remove it.
            data.dragged.remove();
            data.dragged = null;
        }
    }
}

我用來檢查“拖動”狀態變化的代碼片段:

data = {
    canvas: canvas, // The canvas this data belongs to
    gates: [],      // An array of all the logic gates on the canvas
    wires: [],      // An array of all the wires on the canvas
    spawners: [],   // An array of all the spawners on the canvas
    gateWidth: GATE_WIDTH,  // Width of all logic gates on this canvas
    gateHeight: GATE_HEIGHT,// Height of all logic gates on this canvas
    _dragged: null,
    set dragged(obj) {
        log.info("'dragged' is changing to '" + obj + "'.");
        this._dragged = obj;
    },
    get dragged() {
        log.info("'dragged' is being retrieved when it's '" + this._dragged + "'.");
        return this._dragged;
    }
};

當上面的代碼生效時,我得到一個打印輸出,通知我“拖放”已更改為“對象對象”,但是當我移動鼠標(觸發mousemove事件)時,我得到了一個打印輸出,告訴我它是“空”(不是)甚至沒有定義)。 當我項目的其他部分使用它時,它會成功使用它並實際檢索該對象。

您應該使用if (canvas[0] === tmp.canvas[0])引用實際的畫布對象,而不是傳遞給getCanvasData()的jQuery選擇器。

當您檢查if (canvas === tmp.canvas)您是在檢查jQuery選擇器, 不是實際的canvas對象。 因此,在一個地方,您可能傳遞$("canvas#foo")而在其他地方,您傳遞的$("canvas .foo")具有不同的上下文,並且不會彼此==。

暫無
暫無

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

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