2

我正在尝试编写一个通用表生成器,我可以在其中告诉它在每个单元格的 onclick 事件中调用的函数。然后在页面的其他地方定义该函数。

问题是我无法让页面在正确的时刻评估功能。我希望它在构建 DOM 时而不是在触发 click 事件时将我的字符串转换为函数。也许这在 Javascript/JQuery 中是不可能的?

我最初用 C# 编写的服务器端代码的简化版本是:

string functionCall = "DoSomething(4);";
TableCell detailCell = new TableCell();
detailCell.Attributes.Add("onClick", functionCall);
functionCall = "DoSomething(5);";
detailCell = new TableCell();
detailCell.Attributes.Add("onClick", functionCall);

当它在浏览器中呈现为 html 时,这将起作用。它变成了:

 function DoSomething(p)
 {
      alert(p);
 }

<td onclick="DoSomething(4)"></td>
<td onclick="DoSomething(5)"></td>

我想在 Javascript 中复制这个功能。

如果我做:

var functionCall = 'DoSomething(4);';
$('#detailCell').attr('onclick', functionCall);

由于某种原因,它不会在 IE7 中触发该事件,而是在 Chrome 中触发它。

如果我做:

var functionCall = 'DoSomething(4);';
$('#detailCell1').click(function () { eval(functionCall); });
functionCall = 'DoSomething(5);';
$('#detailCell2').click(function () { eval(functionCall); });

那么在添加点击事件时它不会将 functionCall 更改为一段文本。相反,它在单击单元格时评估 functionCall。这意味着 functionCall 的值现在是错误的。

例如,即使我单击 detailCell1,它也总是执行 DoSomething(5),因为那是 functionCall 的最后一个值。

如果我做:

var functionCall = 'DoSomething(4);';
$('#detailCell1').click(eval(functionCall));

它在添加点击事件时立即运行 functionCall 中的函数,而不是在被点击时。

我希望这是有道理的,因为它很难解释。

基本上我只想能够做到

<td onclick="any javascript I feel like storing in a string"></td>

使用 jQuery。

这甚至可能吗?

这是我在stackoverflow上的第一篇文章,所以请温柔...

4

4 回答 4

2

试试这个...

var functionCall = 'DoSomething(4);';

$('#detailCell1').click((function (code) {
  return function () { 
     eval(code); 
  };
}(functionCall)));

这里发生的情况是,您在创建处理程序时通过将字符串分配给参数“code”来捕获字符串。

在您当前的场景中,单击处理程序在单击而不是在创建处理程序时使用字符串的值。

这叫做闭包!

(function (code) {
  return function () { 
     eval(code); 
  };
}(functionCall));

functionCall 值分配给 code 参数。现在,当您更改 functionCall 时,代码参数仍然引用旧值。

于 2013-01-25T11:10:41.563 回答
0

不清楚为什么函数调用应该在字符串中。正如我所看到的,您有许多单元格应该为每个单元格触发一个具有不同参数的函数。

在这种情况下,我接下来会做:

TableCell detailCell = new TableCell();
detailCell.Attributes.Add("class", "detailCell");
detailCell.Attributes.Add("data-num", "4");

detailCell = new TableCell();
detailCell.Attributes.Add("class", "detailCell");
detailCell.Attributes.Add("data-num", "5");

而且,在 js 中的某个地方:

$(function() {
    $(".detailCell").click(function(){
        DoSomething($(this).data("num"));
    });
})

class为了轻松地将点击处理程序分配给所有详细信息单元格,需要在表格单元格上,因此您不需要编写类似的内容:

$('#detailCell1').click(function () { DoSomething(4); });
$('#detailCell2').click(function () { DoSomething(5); });

detailCell.Attributes.Add("data-num", "5");允许放置应该用作参数的数字DoSomething。您可以在这一行中看到它: DoSomething($(this).data("num")); jQuery.data正在使用函数。并将this指向一个被点击的元素。 $(function() {})- 这是jQuery.ready函数的简写。使用它,您可以保证该函数内的代码将在页面准备好使用时执行。

于 2013-01-25T11:19:05.520 回答
0

而不是首先将其创建为字符串然后尝试评估该字符串,您可以简单地创建一个函数值(函数在 JS 中也是对象)

所以而不是

var functionCall = 'DoSomething(4);';
$('#detailCell1').click(eval(functionCall));

$('#detailCell1').click(function(e){DoSomething(4);});

这会为每次点击创建一个新函数。(在您的情况下,您可以省略 e 参数,它只是为了进行任何需要它更容易的更改

如果你有一组要传递的参数,你可以创建一个工厂方法

var doSomethingFactory = function(num){
    return function(e) { DoSomething(num);};
}
$('#detailCell1').click(doSomethingFactory(4));
于 2013-01-25T11:24:57.053 回答
0

根据我的理解,您必须使用不同的参数调用不同的函数。为此,您正在生成字符串并尝试使用 eval() 函数调用这些函数。让我们按如下方式进行。

1.只需将这些函数调用字符串作为数组传递,这样在加载您的 javascript 代码时如下所示,

var functioncalls = ['DoSomething(1)','DoSomethingMore(1,2)','DoDifferent("hello world")'];

2.然后在javascript中循环你的函数调用数组并将它们分配给不同的点击事件,为了避免复杂性,我假设你的选择器是#detailCell0、#detailCell1、#detailCell2等等。然后你的代码如下所示,

$(function(){
      functioncalls.forEach(function(functioncall,index){
          $("detailCell"+index).click(function(){ 
                eval(functioncall);
           })
      });
    })

注意:有很多方法可以做到这一点。

于 2013-01-25T11:32:53.407 回答