编辑:这个问题演变成如何优化大规模的CSS更改为700或更多div。我将在下面留下旧问题来描述我原来的方法。
我有以下jQuery但它的行为并不像我期望的那样。有大约700个div与类gr,所以隐藏它们需要一个明显的时间。我想做的是:
“工作”可以追溯到“显示/隐藏发音”
$(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 there's a jsfiddle for this question.
This is the full page I'm working on
我观察到的行为是“显示/隐藏P”需要一段明显的时间来改变,然后它会短暂地改变为“工作”,然后它会回到“显示/隐藏”状态。那么jQuery将html()和.toggle()聚合在一起,而不是先运行html()吗?
这似乎是浏览器特定的,因为在Opera中它做了我想要的。在IE 7和Chrome 18中,行为如我所述。有没有办法让Chrome中我想要的行为发生?或者更好的方式来做我正在描述的事情?
答案 0 :(得分:6)
编辑:
为什么不在所有元素上交换类,而不是使用toggle函数来绑定事件?这应该更多更快:
$(document).ready(function(){
$('#toggleP').click(function(){
$('.gr').toggleClass('hidden');
});
});
然后在CSS中添加以下样式:
.hidden { display: none !important; }
有关示例,请参阅this fiddle。
其他编辑:
如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()
“预定”10ms。这意味着click()
函数几乎可以立即返回,而无需等待toggle()
完成。
正如其他人所说,最好的选择可能是将所有div
包装在父级中(如果这对您的实际代码可行),然后切换父级div
。
JSFiddle链接:http://jsfiddle.net/5E45Q/
答案 1 :(得分:3)
如果您可以将所有div.g
分组到父元素中,则可以隐藏该单个父元素而无需修改DOM 700次。见http://jsfiddle.net/SVf5k/6/
但如果这是不可避免的,您可以在切换div.g
之前添加一个短暂的延迟。这将为js引擎提供更改#toggleP
上的html的机会。见http://jsfiddle.net/SVf5k/5/
答案 2 :(得分:2)
编辑:我原来的答案旨在解决您为什么只在短暂的时间内看到“工作......”并且直到toggle()
才看到效果的混淆一段时间在实际查看您正在构建的网站时,我可以看到您真正关心的是简单地将此UI更新更快,在这种情况下,我强烈推荐Justin's answer(尽管我也是有兴趣解释为什么会出现如此巨大的性能差异。)
简短的回答:我认为你想要的是一个异步迭代器,我已经看过其他项目的手工滚动,但奇怪的是我不认为我在开源库中看到过(并不意味着它不存在 - 我只是没有看到它。)
你可以看到here它的行为方式(我认为)是你期望的。
现在,为了解释:
jQuery将html()和.toggle()聚合在一起,而不是先运行html()?
我不认为这是jQuery;我相信这是与浏览器相关的行为,关于浏览器的呈现引擎如何处理来自事件循环的UI更新。我知道很多UI实现不是即时更新UI元素,而是仅在处理的每个事件之间。
对于浏览器我的一般观察(我不是真正的权威;你必须与实际的浏览器贡献者交谈)是一些 UI更新立即发生,并且某些除了通过事件循环的每次完整传递外没有可见效果。所以在我看来,无论jQuery在toggle()
的引擎盖下做什么都属于后者。
答案 3 :(得分:1)
一种方法是使用javascript直接动态修改css样式(不是每个元素)。
在您的网页中,每个<td>
中的所有文字div都有class='gr'
个内联style="display:block;"
。首先,我将display:block;
移动到样式表中(最好是第一个位置)。
使用此SO answer(和this page,以及此SO answer),我会浏览每个样式表,直到您获得您感兴趣的样式表(添加标题为<css />
将允许您轻松完成此操作)。删除显示块(这是一个简单的stylesheet.deleteRule(<index>)
索引将为零,因为你把它放在.css中)。添加新的display:none;
。
这将基本上改变页面的整个css,而不是单独更改PER元素,因为你不得不使用JQuery。
也许不是最受欢迎的解决方案,但仍然允许您保留当前的设计(不重复信息)并使用css来实现它的假设(“动态”)。
跟进: 很好找"Totally Pwn CSS with Javascript"。确切地说,我会在你的情况下做什么(想在这里为后人添加:))
另外,有人应该向JQuery提出功能请求,以便能够轻松地执行此类操作。 :)
跟进2: 刚才意识到其他人在我之前发布了解决方案
另一种方法是删除'gr'类并添加另一个'grHide'类。 看看这个fiddle,看看我的意思。
如上所述,将内联display:block;
移动到.gr类下的css样式表中。添加一个单独的类,它可以执行所有操作.gr确实可以执行display:none;
。
这应该允许你使用jquery并且仍然非常快。无论如何,小提琴很快。
答案 4 :(得分: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/
答案 5 :(得分: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");
});
}
})
});
});