jquery addClass 的应用顺序不正确

jquery addClass isn't being applied in the right order

在下面的示例中,我在单击时立即向正文添加 class busy。这应该将背景变成红色。然后我在每个循环完成后删除这个 class。

实际上发生的是 class busy 在循环完成后被添加,然后立即被删除。我知道是这种情况,因为如果我在循环中删除 removeClass 条件,则会添加 class busy 并保持 added.I 不明白为什么。我在这个问题上被困了一个多小时,现在完全停滞不前。

在 fiddle 示例中,单击第 3 列。

Fiddle https://jsfiddle.net/2nvopbqo/3/

$(".sort").click(function() {
  $('body').addClass('busy');
  var col = $(this).parent().children().index($(this));
  var desc = $(this).hasClass('desc');
  var date = $(this).hasClass('date');
  sortTable(desc, col, date);
  $(this).toggleClass("desc asc");
});

function sortTable(order, col, date) {
  var rows = $('#mytable tbody  tr').get();

  rows.sort(function(a, b) {

    var A = $(a).children('td').eq(col).text().toUpperCase();
    var B = $(b).children('td').eq(col).text().toUpperCase();

    if (date) {
      var A = A.split("-").reverse().join('-');
      var B = B.split("-").reverse().join('-');
    }

    if (order) {
      if (B < A) return -1;
      if (B > A) return 1;
    } else {
      if (A < B) return -1;
      if (A > B) return 1;
    }

    return 0;
  });

  var totalRows = rows.length;


  $.each(rows, function(index, row) {
    $('#mytable').children('tbody').append(row);

    if (index == totalRows - 1) $('body').removeClass('busy');
  });
}

您的代码永远不会返回给浏览器以允许它显示在启动工作和删除 class 之前添加 class 导致的更新状态。您的主要 JavaScript 代码在一个线程上运行,该线程也用于更新 UI(这很重要,原因有几个)。

如果你想让 class 的效果被看到,用 setTimeout 返回给浏览器,持续时间为 0 或一个非常小的数字(用你的目标测试浏览器,有时我不得不在 Firefox 上使用 ~40ms):

$(".sort").click(function() {
  $('body').addClass('busy');
  var $this = $(this);
  setTimeout(function() {
    var col = $this.parent().children().index($(this));
    var desc = $this.hasClass('desc');
    var date = $this.hasClass('date');
    sortTable(desc, col, date);
    $this.toggleClass("desc asc");
  }, 40);
});

Updated Fiddle(因为我无法将所有这些 HTML 放在一个答案中)。

所有强制重绘的更改仅在当前功能完成后应用。由于您的点击处理程序既添加又删除 .busy 标记,因此更改未完成。进行排序调用 'async' 将解决此问题。

$(".sort").click(function() {
  $('body').addClass('busy');
  var col = $(this).parent().children().index($(this));
  var desc = $(this).hasClass('desc');
  var date = $(this).hasClass('date');
  //will fire after the click handler is done.
  setTimeout(sortTable,0,desc, col, date); 
  // you could also use requestAnimationFrame
  $(this).toggleClass("desc asc");
});