0

我正在尝试创建一个 Web 应用程序,该应用程序将允许用户定义自定义 JavaScript 函数,然后向他们的用户界面添加一个按钮,该按钮可以很好地执行该函数。

这是代码示例

var customCommands = {
  command1: {
    text: 'Hello Console',
    cFunctionRun: function() {
      console.log('hello Console!');
    }
  },
  command2: {
    text: 'Hello World',
    cFunctionRun: function() {
      alert('hello World!');
    }
  }
}

然后我写了一个小函数,它循环并构建按钮并将它们添加到用户界面。问题是当我将元素附加到用户界面而不是单击按钮时没有任何效果......

这是我尝试过的方法之一

for (var cmd in customCommands) {
    command = customCommands[cmd];
    button = $('<button/>').html(command.text).on('click', 
      function(){ 
        console.log(command.text); 
        command.cFunctionRun(); 
      }
    );
}
buttonContainer.append(button);

现在我的循环构建一切都很好,甚至可以.on('click')正常工作,但它总是显示最后添加的命令的文本?

这是http://jsfiddle.net/nbnEg/显示发生了什么。

4

4 回答 4

2

当您实际单击时,命令变量指向最后一个命令(因为整个循环已经运行)。您应该维护每个按钮的数据状态,告诉它调用哪个命令。你应该做这个。

for(var i in customCommands) {
  if(customCommands.hasOwnProperty(i)){ //this is a pretty important check
    var command = customCommands[i];
    button = $('<button/>').html(command.text).data("command_name", command).on('click', function(){ 
      console.log($(this).data("command_name").text); 
      $(this).data("command_name").cFunctionRun(); 
    });

    $("body").append(button);
  }
}

JSFiddle

于 2013-02-06T20:46:20.510 回答
1

你所需要的只是用函数传递参数,你应该试试这个

于 2013-02-06T20:42:02.680 回答
0

这是一个(缺失的)闭包问题。事件处理程序将在循环的最后一次迭代中保留对 command 值的引用。要解决它,您可以使用立即调用的函数创建一个新范围:

for(var cmd in customCommands) {
    (function(command){
        button = $('<button/>').html(command.text).on('click', 
          function(){ 
            console.log(command.text); 
            command.cFunctionRun(); 
          }
        );
        buttonContainer.append(button);
    }(customCommands[cmd]));
}
于 2013-02-06T20:48:11.820 回答
0

由于buttons 应该是唯一的(没有理由创建重复项),因此我将按钮设置idnamecustomCommands 的按钮(在本例中为 command1 和 command2)。这个例子可以很容易地适应使用任何相关属性(data-*、name 等)。

每当按下您的其中一个时,创建一个click事件侦听器。然后调用与给定关联的函数。documentbuttonid

$(document).on("click", "button", function(){
    customCommands[this.id].cFunctionRun();
});

for(var command in customCommands){
    var button = $('<button id="' + command +'"/>').html(customCommands[command].text);
    $("body").append(button);
}

例子

于 2013-02-06T20:53:22.807 回答