【问题标题】:jquery and id selector issuejquery 和 id 选择器问题
【发布时间】:2018-02-03 20:55:00
【问题描述】:

我需要为页面上创建的一些按钮生成随机 ID。我使用这个 jquery 创建按钮:

var btnId = 'delete-' + row.id;
$("<button/>", {
    'id': btnId,
    'html': $("<i></i>").addClass("ion-icon ion-btn ion-trash-a"),
    'class': 'btn btn-primary btn-md'
}).append(' Delete')

按钮 id 的模板:

delete-$UUID,其中$UUID 是从数据库中检索的。

这很好用,创建后,我什至可以使用 jquery 为每个按钮附加一个点击监听器:

$('button#' + btnId).click(function(e) { alert("Button clicked!"); });

情节变厚

现在,我决定不使用数据库行 id,而是生成一个随机字符串用作按钮 id,所以我创建了这个函数:

function _randomString (min, max) {
    var text = "";
    var length = Math.floor(Math.random() * (max - min) + min);
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZ-abcdefghijklmnopqrstuvwxyz0123456789";
    for (var i = 0; i < length; i++) {
        text += possible.charAt(Math.floor(Math.random() * possible.length));
    }
    return text;
}

,然后像这样替换按钮id

var btnId = 'delete-' + _randomString(20, 30);

如您所见,唯一不同的是$UUID 被我创建的这个函数的值所取代。

高潮

现在,当我使用 jquery 添加点击侦听器(与上面相同的 jquery)时,绑定停止使用 jquery。无论发生什么,jquery 似乎都不想在使用这样的 id 创建时找到并绑定单击侦听器。

起初,我以为这可能是由于函数没有生成随机字符串,但我去控制台并获取了其中一个按钮的生成ID,当我执行$('copied-button-id').length时,我得到了@987654331 @。很明显,jquery 能够找到按钮 now,但不是在创建按钮时,就像我使用数据库行 id 创建按钮 id 时那样。

更奇怪的是,当我删除随机生成的字符串并将其替换为像sdfsdfsd 这样的普通字符串时,即现在所有按钮的 id 为delete-sdfsdfsd,jquery 可以毫无问题地找到并绑定到按钮。

在有人问之前,我还仔细阅读了 html 元素的可接受 id,所以这不是问题。 What are valid values for the id attribute in HTML?

分辨率

这是我需要你帮助的地方。我想我要么真的很累,要么什么,但你能看看我的功能,告诉我可能是什么导致了这个问题。我已经消除了长度问题,因为我已经能够使用长度超过 60 个字符的 id 并且它们都有效。通过能够找到(或不)以这种方式创建的任何按钮,JQuery 是否表现出未定义的行为?我是否表现出不确定的行为?我错过了什么?

欢迎任何帮助!


JQuery 版本:2.1.4

MCVE:

$(function() {
  var numRows = 10;
  var $table = $('#db-table');
  for (var i = 0; i < numRows; i++) {
    $table.find('tbody').append("<tr/>");
    var name = _randomString(5, 10);
    var age = Math.floor(Math.random() * 25 + 5);
    var $row = $table.find('tbody tr:eq(' + i + ')');
    $row.append($("<td/>", {
      html: "<span>" + name + "</span>"
    })).append($("<td/>", {
      html: "<span>" + age + "</span>"
    })).append(_getButton({
      id: _randomString(20, 30)
    }));
  }
});

function _randomString(min, max) {
  var text = "";
  var length = Math.floor(Math.random() * (max - min) + min);
  var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZ-abcdefghijklmnopqrstuvwxyz0123456789";
  for (var i = 0; i < length; i++) {
    text += possible.charAt(Math.floor(Math.random() * possible.length));
  }
  return text;
}

function _getButton(row) {
  var btnId = 'delete-' + row.id;
  var $btn = $("<button/>", {
    'id': btnId,
    'html': $("<i></i>").addClass("ion-icon ion-btn ion-trash-a"),
    'class': 'btn btn-primary btn-md'
  }).append(' Delete');

  $('button#' + btnId).click(function(e) {
    alert("You clicked a button!!");
  });

  return $btn.prop('outerHTML');
}
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<div class="container">
  <div class="row">
    <table id="db-table" class="table-responsive">
      <thead>
        <tr>
          <th>Name</th>
          <th>Age</th>
          <th>Actions</th>
        </tr>
      </thead>
      <tbody></tbody>
    </table>
  </div>
</div>

【问题讨论】:

  • 为什么需要身份证?您可以直接创建元素并将事件处理程序绑定到元素。
  • 我看不出它为什么不起作用的任何原因。您需要发布一个演示问题的 MCVE,以便我们可以看到您做错了什么。
  • 它在这里工作:jsfiddle.net/barmar/h8hetw2t/1 当我复制你的代码时,我发现你在$("button#" + btnId).click( 行的末尾缺少一个)
  • @James,比如...?
  • $('button#' + btnId).on('click', function(e) { alert("Button clicked!"); }); 对于动态添加到 DOM 的元素,您必须使用 .on() 方法委托事件。

标签: javascript jquery html random


【解决方案1】:

您在_getButton() 函数中使用了选择器$("button#' + btnId)。但是在函数返回并将按钮传递给$row.append()之前,按钮不会附加到DOM。

相反,只需绑定到元素本身,而不是使用选择器。而_getButton() 需要返回元素本身,而不是它的outerHTML,因为那样会丢失事件绑定。

$(function() {
  var numRows = 10;
  var $table = $('#db-table');
  for (var i = 0; i < numRows; i++) {
    $table.find('tbody').append("<tr/>");
    var name = _randomString(5, 10);
    var age = Math.floor(Math.random() * 25 + 5);
    var $row = $table.find('tbody tr:eq(' + i + ')');
    $row.append($("<td/>", {
      html: "<span>" + name + "</span>"
    })).append($("<td/>", {
      html: "<span>" + age + "</span>"
    })).append(_getButton({
      id: _randomString(20, 30)
    }));
  }
});

function _randomString(min, max) {
  var text = "";
  var length = Math.floor(Math.random() * (max - min) + min);
  var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZ-abcdefghijklmnopqrstuvwxyz0123456789";
  for (var i = 0; i < length; i++) {
    text += possible.charAt(Math.floor(Math.random() * possible.length));
  }
  return text;
}

function _getButton(row) {
  var btnId = 'delete-' + row.id;
  var $btn = $("<button/>", {
    'id': btnId,
    'html': $("<i></i>").addClass("ion-icon ion-btn ion-trash-a"),
    'class': 'btn btn-primary btn-md'
  }).append(' Delete');

  $btn.click(function(e) {
    alert("You clicked a button!!");
  });

  return $btn;
}
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<div class="container">
  <div class="row">
    <table id="db-table" class="table-responsive">
      <thead>
        <tr>
          <th>Name</th>
          <th>Age</th>
          <th>Actions</th>
        </tr>
      </thead>
      <tbody></tbody>
    </table>
  </div>
</div>

【讨论】:

  • 感谢您迄今为止的帮助。我发现使用行 ID 起作用的原因是因为表被加载了两次(一次是检索数据并加载 HTML,第二次是刷新表以防某些数据丢失)。问题是,第一次生成行时,jquery 绑定尝试绑定到页面上尚存在的元素,第二次重新生成 id 并且再次没有这样的元素附加监听器的页面。使用 row id 有效,因为第二次,元素在那里,jquery 可以附加侦听器。
【解决方案2】:

似乎完全没有必要为此使用 ID。只需使用 CSS 类,将单击事件绑定到具有该类的所有按钮,如果您需要对与该按钮关联的行或数据执行特定操作,请在元素上使用 html5 data 标签,或仅使用 @987654322 @ 或 $(this).closest(...) 获取单击按钮时所需的任何信息。

同样,这里的用例并不是 100% 清楚,但只是为了举例,假设您的按钮类是 awesome-button

// Using $(document).on('click') instead of just
// $('.awesome-button').click() since you seem to be dynamically creating buttons.

$(document).on('click', '.awesome-button', function() {
  var row = $(this).closest('tr');

  // Now do whatever you want with the row...
  row.find('.something-obscure');

  // Or maybe your rows have data tags on them that need to go somewhere?
  someCrazyFunction(row.data('example'));

  // etc...
});

【讨论】:

  • 按钮执行与为其创建按钮的行相对应的特定操作。使用一个 css 类将意味着按下按钮时只有一行会受到影响。我使用alert 的示例只是为了说明问题,用例实际上比这要复杂得多
  • @smac89 这就是使用$(this).closest("tr") 之类的东西来查找包含按钮的行的意义所在,然后您可以针对该行执行一些特定的操作。
  • 刚刚更新了我的答案,也许可以让它更清楚......我无法想象有什么如此复杂,以至于你无法从按钮所在的位置遍历 DOM 树来获取你能做的一切可能需要。
  • @BenFried,也许令人困惑的是您没有意识到我有很多按钮(请参阅我对 MVCE 的更新问题)。使用简单的类会触发页面中所有按钮的事件,所以需要一个Id
  • 一个类不会在页面上的所有按钮上触发事件,它会为被点击的ONE按钮触发事件,并且根据被点击的那个,你可以找到任何你想要的数据需要相对于它的位置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-04
  • 2011-10-31
  • 2010-12-01
  • 2010-11-25
相关资源
最近更新 更多