4

编辑:问题变成了如何将大规模 CSS 更改优化为 700 个或更多 div。我将在下面留下旧问题来描述我的原始方法。

我有以下 jQuery,但它的行为不像我预期的那样。大约有 700 个具有 gr 类的 div,因此隐藏它们需要相当长的时间。我正在尝试做:

  1. 单击“显示/隐藏发音”时,立即将该文本更改为“工作中”
  2. 等到所有 'div.gr' 都被隐藏/显示
  3. “工作”回到“显示/隐藏发音”

    $(document).ready(function () {
     $('#togglePron').click(function() {
       $('#togglePron').html("Working...");
       $('div.gr').toggle();
       $('#togglePron').html("Show/hide Pronunciation");
      });
    });
    ...
    ... 
    <div class="pronlink" id="togglePron">Show/hide P</div>
    
    <div class="gr">hai</div><div class="zi">A</div>
    <div class="gr">nao</div><div class="zi">B</div>  
    etc.
    

感谢 Mike Lentini ,这个问题有一个 jsfiddle。

这是我正在处理的完整页面

我观察到的行为是“显示/隐藏 P”需要很长时间才能更改,然后它会短暂更改为“工作”,然后又回到“显示/隐藏”。那么 jQuery 是否将 html() 和 .toggle() 捆绑在一起,而不是先运行 html()?

这似乎是特定于浏览器的,因为在 Opera 中它可以满足我的需求。在 IE 7 和 Chrome 18 中,行为如我所述。有没有办法让我在 Chrome 中想要的行为发生?还是做我所描述的更好的方法?

4

6 回答 6

6

编辑 :

与其使用切换功能来绑定事件,不如直接在所有元素上交换一个类?这应该更快

$(document).ready(function(){
  $('#toggleP').click(function(){
    $('.gr').toggleClass('hidden');
  });
});

然后在你的 CSS 中,添加这个样式:

.hidden { display: none !important; }

有关示例,请参见此小提琴。

附加编辑:

正如kingjeffrey所指出的,交换父元素而不是子元素的类交换效率更高:

JS:
$('#togglePron').click(function(){
  $('table').toggleClass('hide-pron');
});

CSS:
table.hide-pron .gr { display: none !important; }

对于(相对)少量的孩子,这些方法之间的差异可以忽略不计——但随着孩子数量的增加,交换父类的速度会明显更快。


原始答案:

click()在函数返回之前,您的元素不会更新。这是一种方法(可能不是最好的方法):

$(document).ready(function () {
  $('#toggleP').click(function() {
    $('#toggleP').html("Working...");
    setTimeout(
      "$('div.g').toggle(10,function(){$('#toggleP').html('Show/Hide P');});",
      10)
  });
});

现在toggle()是异步的,因为在未来通过setTimeout(). 这意味着该click()函数几乎可以立即返回,而无需等待toggle()完成。

正如其他人所指出的那样,最好的选择可能是将所有divs 包装在 parent 中(如果这对您的实际代码可行),然后切换该 parent div

JSFiddle 链接:http: //jsfiddle.net/5E45Q/

于 2012-04-09T21:07:53.667 回答
3

如果您可以将所有的div.g's 分组在一个父元素中,您将能够隐藏该单个父元素而无需修改 DOM 700 次。见http://jsfiddle.net/SVf5k/6/

但如果这是不可避免的,您可以在切换div.g's. 这将使 js 引擎有机会更改 .html 上的 html #toggleP。见http://jsfiddle.net/SVf5k/5/

于 2012-04-09T21:17:40.120 回答
2

编辑:我最初的回答旨在解决您对为什么只看到“正在工作......”很短时间并且toggle()直到一段时间后才看到效果的困惑。在实际查看您正在构建的网站时,我可以看到您真正关心的是让这个 UI 更新更快,在这种情况下,我强烈推荐贾斯汀的回答(尽管我也有兴趣解释为什么会有这样的那里有巨大的性能差异)。


简短的回答:我认为你想要的是一个异步迭代器,我已经在其他项目中看到过它,但奇怪的是我认为我没有在开源库中看到过(并不意味着它不存在- -我只是没见过)。

像这样的东西。

你可以在这里看到它的行为方式(我认为)你所期望的。

现在,为了解释:

那么 jQuery 是否将 html() 和 .toggle() 捆绑在一起,而不是先运行 html()?

我不认为它是 jQuery;关于浏览器的渲染引擎如何处理来自事件循环的 UI 更新,我相信您所看到的是与浏览器相关的行为。我知道很多 UI 实现不会立即更新 UI 元素,而只会在处理的每个事件之间更新。

对于浏览器,我的一般观察(我并不是这方面的权威;您必须与实际的浏览器贡献者交谈)是一些UI 更新会立即发生,而有些更新除了在每个完整的通过事件循环。所以在我看来,无论 jQuery 在幕后做什么toggle()都属于后者。

于 2012-04-10T14:54:36.517 回答
1

一种方法是使用 javascript 直接(而不是每个元素)动态修改您的 css 样式。

在您的页面中,每个 div 中的所有文本 div 中<td>都有一个class='gr'WITH 一个 inline style="display:block;"。首先,我将 移到display:block;样式表中(最好移到第一个位置)。

使用这个SO 答案(和这个页面,还有这个SO 答案),我会浏览每个样式表,直到你得到你感兴趣的那个(添加一个标题<css />可以让你轻松地做到这一点)。删除显示块(这是一个简单的stylesheet.deleteRule(<index>)索引将为零,因为您将它放在 .css 中的第一个)。添加一个新的display:none;.

这将实质上改变页面的整个 css,而不是单独改变它们 PER 元素,因为你被迫使用 JQuery。

也许不是最流行的解决方案,但仍然允许您保留当前的设计(不复制信息)并使用 css 来完成它应该做的事情(虽然“动态”)。


跟进: 很好的发现“完全 Pwn CSS with Javascript”。完全符合我在您的情况下会做的事情(想在此处添加以供后代使用:))

在旁注中,有人应该向 JQuery 提出功能请求,以便能够轻松地做这样的事情。:)


跟进 2: 刚刚意识到其他人在我之前发布了解决方案

另一种方法是删除“gr”类并添加另一个“grHide”类。看看这个小提琴,看看我的意思。

按照我上面说的做,将内联display:block;移到 .gr 类下的 css 样式表中。添加一个单独的类,它可以完成 .gr 所做的所有事情,但会做 a display:none;

这应该允许您使用 jquery 并且仍然非常快。无论如何,小提琴很快。

于 2012-04-10T11:40:37.677 回答
0

如果你查看 jQuery 文档,你会看到它toggle()有一个回调——尽管如果你想要一个回调,你还必须指定一个持续时间。所以你的代码可能看起来像:

$(document).ready(function () {
  $('#toggleP').click(function() {
    $('#toggleP').html("Working...");
    $('div.g').toggle(500, function() {
      $('#toggleP').html("Show/hide P");
    });
  });
});
...
... 
<div class="plink" id="toggleP">Show/hide P</div>

如果半秒对你来说是一个很好的持续时间。在此处查看更多信息:http: //api.jquery.com/toggle/

编辑:快速 jsfiddle:http: //jsfiddle.net/SVf5k/

于 2012-04-04T23:31:27.190 回答
0

在这里使用$.ajax()小提琴:http: //jsfiddle.net/SVf5k/10/

$(function () {
    $('#toggleP').click(function() {
       $(this).html("...Working...");

        $.ajax({
           success: function(){
              $('div.g').toggle(500, function() {
                     $('#toggleP').html("Show/hide P");
              });
          }
      })
  });
});
​
于 2012-04-10T14:59:31.480 回答