繁体   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