繁体   English   中英

如何在Javascript中向带有元素数组的参数添加事件处理程序?

[英]How to Add Event Handler with Arguments to an Array of Elements in Javascript?

我有一个完整依赖于JavaScript和Ajax的三步流程来加载数据并使流程从一个步骤动画到下一个步骤。 更复杂的是,步骤之间的转换(向前和向后)是动画的:-(。当用户通过进程锚点的进度显示当前步骤和前面的步骤时。如果他们点击上一步,则将它们带回上一步。

现在,如果从步骤1开始,整个过程(向前和向后)都能正常工作,但如果直接跳到步骤3,则步骤1和步骤2的锚点也会执行与步骤3相同的操作。

这是代码的一部分,循环遍历用户所在的当前步骤的所有步骤,并依次显示每个锚点并为click事件分配适当的函数:

for (var i = 0; i < profile.current + 1; i++) {
    if ($('step_anchor_' + i).innerHTML.empty()) {
        var action = profile.steps[i].action;
        var dao_id = profile.steps[i].dao_id;

        $('step_anchor_' + i).innerHTML = profile.steps[i].anchor;
        $('step_anchor_' + i).observe('click', function(){
            pm.loadData(action, dao_id, true);
        });

        Effect.Appear('step_anchor_' + i, {
            duration: 1,
            delay: (down_delay++)
        });
    }
}

我知道问题在于传递action和dao_id参数的方式。我也尝试传递profile.steps [i] .action和profile.steps [i] .dao_id但是在这种情况下我们都是profile和i或者至少我的范围。

我该怎么做才能为每个步骤正确分配action和dao_id的参数? (如果它有任何区别我们正在使用Prototype和Scriptaculous)

您的关闭范围链导致您的问题。 通过内联声明处理函数,您已经创建了一个闭包。 显然你这样做是为了利用循环。

但是,由于您已经创建了一个闭包,因此您将使用闭包范围规则。 这些规则声明只要闭包存在,父函数中的局部变量就会保持活动状态并且可用。

你试图传递然后使用“action”和“dao_id”到你的闭包,但你在这里传递引用,而不是值。 因此,当调用闭包(处理程序)时,它们使用上次分配引用的值。 在您的情况下,步骤3处理程序。

关闭范围规则很容易混淆,但是即使循环块已经完成执行,“action”和“dao_id”仍然存在这一事实也可能会让您感到困惑。 好吧,在JavaScript中没有块范围这样的东西。 声明变量后,它将一直可用,直到函数结束或直到删除为止。 以先到者为准。

总而言之,你需要打破范围链。 这有两种方法:

尝试这个:

for (var i = 0; i < profile.current + 1; i++) {
    if ($('step_anchor_' + i).innerHTML.empty()) {
        var action = profile.steps[i].action;
        var dao_id = profile.steps[i].dao_id;

        $('step_anchor_' + i).innerHTML = profile.steps[i].anchor;
        $('step_anchor_' + i).observe('click', function(a, b){
                return function(){pm.loadData(a, b, true)};
        }(action, dao_id));

        Effect.Appear('step_anchor_' + i, {
                duration: 1,
                delay: (down_delay++)
        });
    }
}

或这个:

function createHandler(action, dao_id) {
    return function(){pm.loadData(action, dao_id, true);};
} 

/* snip - inside some other function */
for (var i = 0; i < profile.current + 1; i++) {
    if ($('step_anchor_' + i).innerHTML.empty()) {
        var action = profile.steps[i].action;
        var dao_id = profile.steps[i].dao_id;

        $('step_anchor_' + i).innerHTML = profile.steps[i].anchor;
        $('step_anchor_' + i).observe('click', createHandler(action, dao_id));
        Effect.Appear('step_anchor_' + i, {
                duration: 1,
                delay: (down_delay++)
        });
    }
}

首先,记住click事件中的执行范围。 该上下文中的this关键字指的是被单击的元素。 有没有办法可以从点击的元素中确定dao_id?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM