【问题标题】:How to create an hyperlink whose onclick handler is an anonymous function?如何创建其 onclick 处理程序是匿名函数的超链接?
【发布时间】:2011-06-16 05:53:44
【问题描述】:

我正在尝试动态生成 flexigrid 生成表的单元格的 onclick 事件处理程序:

// ...
preProcess: function (data) {
    var rows = data.rows;
    for (var i = 0; i < rows.length; ++i) {
        var row = rows[i];
        // If and only if this condition is true, then
        // row.cell[0] must be converted into a hyperlink.
        if (row.cell[1] != '0') {
            // I don't want to use the href attribute, because that would
            // force me to define a non-anonymous function.
            row.cell[0] = '<a href="javascript:void(0)" id="E'
                        + i + '">' + row.cell[0] + '</a>';
            // So I'm going to try assigning the onclick attribute.
            $('#E' + i).click(function () {
                window.open('doc.php?q=' + this.id, 'D' + this.id,
                            'menubar=0,toolbar=0,directories=0,location=0,status=0,' +
                            'resizable=0,scrollbars=0,width=600,height=300');
            });
            $('#E' + i).click().id = row.cell[4];
        }
    }
    return data;
}
// ...

但是,当我单击生成的超链接时,它们不起作用。有什么问题?我使用闭包? &lt;a&gt; 标签不接受onclick 属性?


注意:自从我开始使用 jQuery,我的策略是所有函数都应该是匿名函数。请不要建议我使用普通函数。

【问题讨论】:

  • 出于好奇,为什么必须'所有函数......都是匿名函数'?无意批评,我只是真诚地好奇。
  • 我想推动自己学习和掌握EVERY的概念。
  • “所有函数都应该是匿名函数” 我采取了类似的策略——所有的锤子都应该是蓝色的。不要建议我使用红锤。
  • 如果您想学习和掌握每一个概念,请从使用正确工具的概念开始:)
  • jQuery 没有规定匿名函数的使用,当然也不是唯一的。如果您想使用.unbind(),您可能会遇到麻烦。对我来说,匿名函数的独占使用听起来像是等待发生的内存泄漏。

标签: javascript jquery html closures flexigrid


【解决方案1】:

看起来您正在使用原始字符串连接创建&lt;a&gt;,然后分配它......在哪里?如果链接不是 DOM 的一部分,那么 $('linkID') 将找不到任何内容,从而有效地将您的点击处理程序分配给任何内容。 jQuery 选择器只搜索 DOM。

【讨论】:

  • Flexigrid 稍后会将超链接分配到表格单元格中。
  • @Eduardo 关键是——“稍后”。比如,在你打电话给$().click()?
  • 噢噢噢噢!是的。在那之后。
【解决方案2】:

使用 jQuery(或浏览器的原生 dom 函数)创建元素并附加事件处理程序:

$('<a href="#" id="E' + i + '"/>').html(row.cell[0]).click(function(e) {
    e.preventDefault();
    // your code
});

【讨论】:

  • 我告诉 Rex M,Flexigrid 稍后会创建该元素。但是,正如 Rex M 告诉我的,jQuery 选择器只适用于已经创建的元素。
【解决方案3】:

首先,您似乎没有在附加您的 id='#E' + i。

所以,我猜当你调用 $('#E' + i) 时,它会返回一个空的 jQuery 对象。您可以通过警告 $('#E' + i).length 来检查这一点。 0 表示未找到任何内容。

其次,您不需要 javascript:void(0) 调用。只需将其替换为 '#' 并在您的匿名函数中调用 event.preventDefault() 即可。您还需要将事件作为参数传递给匿名函数。

【讨论】:

    【解决方案4】:

    您正试图将onclick 事件连接到一个尚不存在的元素上。当时,该元素仅以文本形式存在于数组中,由于代码尚未添加到 DOM 中,因此选择器无法找到它。

    如果您想为事件处理程序使用匿名函数,则必须等待连接事件,直到创建元素以使其作为对象存在。

    【讨论】:

      【解决方案5】:

      我复制了您的代码,经过一些小的更正后,我成功了。我假设数据是指一个表对象。这是我的代码和虚拟 HTML。

      <html>
        <head>
          <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.min.js"></script>   
        </head>
        <body>
          <table id='myTable'>
            <tr>
              <td>x</td><td>1</td><td>a</td><td>f</td><td>p</td>
            </tr>
            <tr>
              <td>y</td><td>2</td><td>b</td><td>g</td><td>q</td>
            </tr>
          </table>
          <script>
            function preProcess(data) {
              var rows = data.rows;
              for (var i = 0; i < rows.length; ++i) {
              var row = rows[i];
              // If and only if this condition is true, then
              // row.cell[0] must be converted into a hyperlink.
              if (row.cells[1] != '0') {
              // I don't want to use the href attribute, because that would
              // force me to define a non-anonymous function.
                row.cells[0].innerHTML = '<a href="javascript:void(0)" id="E' + i + '">' 
                                     + row.cells[0].innerHTML + '</a>';
              // So I'm going to try assigning the onclick attribute.
                $('#E' + i).click(function () {
                        window.open('doc.php?q=' + this.id, 'D' + this.id,
                          'menubar=0,toolbar=0,directories=0,location=0,status=0,' +
                          'resizable=0,scrollbars=0,width=600,height=300');
                });
                //$('#' + id).click().id = row.cells[4];
                }
              }
              return data;
            }  
      
            $(document).ready(function() {
              preProcess(document.getElementById('myTable'));
            });
      
          </script>
        </body>
      </html>
      

      我的更正如下(我认为有些可能是由于您复制帖子代码时的转录):

      1. 我用单元格替换了单元格
      2. 我在单元格索引后添加了 innerHTML
      3. 我将链接设置为 javascript:void 而不是 javascript.void
      4. 我注释掉了 $('#' + id).click().id = row.cells[4]; 行,因为我不知道它做了什么。

      有了这些变化,它就像一个魅力。

      我希望这会有所帮助。

      【讨论】:

        【解决方案6】:

        听起来您正在寻找的是 live()

        将处理程序附加到与当前选择器匹配的所有元素的事件,现在和将来

        实际上,它允许您为尚不存在的元素创建事件处理程序。 我觉得您只想对当前代码进行最少的更改以使其正常工作。在这种情况下,live() 是你最好的选择,因为你的代码只会从

        $('#E' + i).click(function () { ...
        

        $('#E' + i).live('click', function () { ...
        

        【讨论】:

        • 您应该已经注意到,通过每个元素的 id 为每个元素创建一个实时事件根本不是最优的。
        【解决方案7】:

        使用 jQuery 的 live 事件。

        为了便于查看发生了什么,我还在链接中添加了一个类,因为我假设页面上还有其他链接,.

        function preProcess(data) {
            ...
            row.cell[0] = '<a href="#" class="clickMe" id="E' + i + '">' + row.cell[0] + '</a>';
        }
        
        jQuery("a.clickMe").live("click", function(event) {
            event.preventDefault();
            window.open('doc.php?q=' + this.id, 'D' + this.id, .....
        });
        

        免责声明:我从未使用过 flexigrid,但从您的其他 cmets 看来,您可以在 flexigrid 将内容放入 DOM 之前对其进行修改。

        在将元素添加到 DOM 之前,实时事件允许连接单个处理程序(匿名或非匿名)。

        见:jQuery live()

        .live()

        将处理程序附加到事件 对于所有匹配的元素 当前选择器,现在和在 未来

        【讨论】:

          猜你喜欢
          • 2016-08-07
          • 1970-01-01
          • 2022-12-04
          • 1970-01-01
          • 2017-11-13
          • 2010-11-26
          • 2020-05-31
          • 2022-11-14
          • 1970-01-01
          相关资源
          最近更新 更多