我正在尝试为vis.js网络创建一个点击事件处理程序,如this example:
中显示的那样network.on("click", function (params) { params.event = "[original event]"; document.getElementById('eventSpan').innerHTML = '<h2>Click event:</h2>' + JSON.stringify(params, null, 4); console.log('click event, getNodeAt returns: ' + this.getNodeAt(params.pointer.DOM)); });`
但是我试图在循环中这样做,并希望匿名事件处理函数能够在循环中使用局部变量(在连续迭代中更改它们之前)。
例如:
for (data in data_list) {
var network = new vis.Network(data['container'], data['data'], data['options']);
network.on("click", function(params) {
console.log(data) // On event, data always equal to last element in data_list. I want it to save the data from the iteration this function was created in
console.log(params) // I also need to access 'params'
}
}
我理解这应该通过闭包来完成,但是我找不到任何如何执行此操作的示例,同时还要保持对&#39; params&#39;的访问权限。传入。我怎么能创建一个可以接受&#39; params&#39;参数但也保存了数据&#39;?
的状态答案 0 :(得分:1)
我通常将函数外部化,传递我想要保留的数据并返回一个接受处理程序参数的函数:
function getOnClickHandler(data) {
return function(params) {
console.log(data);
console.log(params);
}
}
for (data in data_list) {
var network = new vis.Network(data['container'], data['data'], data['options']);
network.on("click", getOnClickHandler(data));
}
答案 1 :(得分:0)
for (data in data_list) {
var network = new vis.Network(data['container'], data['data'], data['options']);
network.on("click", (params) => {
console.log(data) // On event, data always equal to last element in data_list. I want it to save the data from the iteration this function was created in
console.log(params) // I also need to access 'params'
}
}
如果您需要进一步澄清,请与我们联系。
答案 2 :(得分:0)
啊,在Javascript循环gotcha中的回调'。
为什么会发生这种情况的解释是,在收到点击事件之前,您的代码会完整地执行。它意味着它通过创建新网络,定义新的onClick处理程序,然后将它们添加到网络来循环。虽然这些处理程序中的每一个都是独立的,但它们都捕获相同的数据变量,这将在循环结束时引用到最后一个数据元素。
var arr = [1, 2, 3, 4, 5]
for (i in arr) {
setTimeout(function () { console.log(i) }, 1000);
}
// prints 4, 4, 4, 4, 4
有两种方法可以解决此问题。第一种方法是利用ES 6的let
声明,它使变量成为块作用域(例如for循环体),vs var
声明作为函数作用域。
var arr = [1, 2, 3, 4, 5]
for (let i in arr) { // NOTE THE USE OF let HERE.
setTimeout(function () { console.log(i) }, 1000);
}
// prints 0, 1, 2, 3, 4
第二种方法是将var
传递给函数,以便为每个循环代码创建一个新变量,该代码的作用域是该函数。
function handlerWrapper(i) {
return function() { console.log(i) };
}
var arr = [1, 2, 3, 4, 5]
for (i in arr) {
setTimeout(handlerWrapper(i), 1000);
}
// prints 0, 1, 2, 3, 4
通过这种安排,您的参数应该适用于您的回调函数:
function handlerWrapper(data) {
return function(params) { console.log(data, params) };
}