什么会导致 jQuery 的 unbind 功能无法按预期工作?
看一下下面的代码(此外,您将需要 jquery.js, jquery.viewport.js 和 jquery.scrollTo.js)。
我期望此脚本的行为是,每当我滚动页面时,红色行(具有 alwaysVisible
类的 元素)应插入到顶部下方- 该表最可见的行(
元素)。然后,应该滚动页面,以便这些红色行中的第一行“恰好”出现在视口的顶部。实际发生的情况是,
makeVisibleWhatMust();
被重复调用,直到到达页面末尾。我认为 $(window).unbind('scroll'); 会阻止 makeVisibleWhatMust();
再次被调用,但显然这不起作用。
有什么想法吗?
这是我编写的 JavaScript:
function makeVisibleWhatMust()
{
$('#testContainer').text( $('#testContainer').text() + 'called\n');
$('table.scrollTable').each
(
function()
{
var table = this;
$($('tr.alwaysVisible', table).get().reverse()).each
(
function()
{
$(this).insertAfter( $('tr:in-viewport:not(.alwaysVisible)', table)[0] );
}
);
$(window).unbind('scroll');
$(window).scrollTo( $('tr.alwaysVisible')[0] );
$(window).bind('scroll', makeVisibleWhatMust);
}
);
}
$(document).ready
(
function()
{
$(window).bind('scroll', makeVisibleWhatMust);
}
);
这是一个用于测试它的 HTML 页面:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Scroll Tables Test Page</title>
<script type="text/javascript" src="jQuery.js"></script>
<script type="text/javascript" src="jquery.viewport.js"></script>
<script type="text/javascript" src="jquery.scrollTo.js"></script>
<script type="text/javascript" src="scrollTable.js"></script>
<style type="text/css">
table th, table td
{
border: 1px solid #000;
padding: .3em;
}
.alwaysVisible
{
background: #F66;
}
</style>
</head>
<body>
<table class="scrollTable">
<thead>
<tr class="alwaysVisible">
<th>Row name</th>
<th>Content</th>
</tr>
<tr class="alwaysVisible">
<th>Row 2</th>
<th>Row 2</th>
</tr>
</thead>
<tbody>
<script type="text/javascript">
for(var i = 0; i < 50; ++i)
{
document.writeln("<tr><td>Row " + i + "</td><td>Content</td></tr>");
}
</script>
</tbody>
<tfoot>
<tr>
<td>Footer</td>
<td>Footer 2</td>
</tr>
</tfoot>
</table>
<div id="testContainer">TEST CONTAINER</div>
</body>
</html>
Have a look at the following code (additionally, you will need jquery.js, jquery.viewport.js and jquery.scrollTo.js).
The behaviour I would expect from this script is that whenever I scroll the page, the red rows (<tr>
elements with class alwaysVisible
) should be inserted just underneath the top-most visible row (<tr>
element) of that table. Then, the page should be scrolled so that the first of these red rows appears "exactly" at the top of the viewport. What actually happens is that makeVisibleWhatMust();
is called repeatedly until I reach the end of the page. I thought $(window).unbind('scroll');
would keep makeVisibleWhatMust();
from being called again, but apparently this doesn't work.
Any ideas why?
Here is the JavaScript I wrote:
function makeVisibleWhatMust()
{
$('#testContainer').text( $('#testContainer').text() + 'called\n');
$('table.scrollTable').each
(
function()
{
var table = this;
$($('tr.alwaysVisible', table).get().reverse()).each
(
function()
{
$(this).insertAfter( $('tr:in-viewport:not(.alwaysVisible)', table)[0] );
}
);
$(window).unbind('scroll');
$(window).scrollTo( $('tr.alwaysVisible')[0] );
$(window).bind('scroll', makeVisibleWhatMust);
}
);
}
$(document).ready
(
function()
{
$(window).bind('scroll', makeVisibleWhatMust);
}
);
And here is an HTML page to test it on:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Scroll Tables Test Page</title>
<script type="text/javascript" src="jQuery.js"></script>
<script type="text/javascript" src="jquery.viewport.js"></script>
<script type="text/javascript" src="jquery.scrollTo.js"></script>
<script type="text/javascript" src="scrollTable.js"></script>
<style type="text/css">
table th, table td
{
border: 1px solid #000;
padding: .3em;
}
.alwaysVisible
{
background: #F66;
}
</style>
</head>
<body>
<table class="scrollTable">
<thead>
<tr class="alwaysVisible">
<th>Row name</th>
<th>Content</th>
</tr>
<tr class="alwaysVisible">
<th>Row 2</th>
<th>Row 2</th>
</tr>
</thead>
<tbody>
<script type="text/javascript">
for(var i = 0; i < 50; ++i)
{
document.writeln("<tr><td>Row " + i + "</td><td>Content</td></tr>");
}
</script>
</tbody>
<tfoot>
<tr>
<td>Footer</td>
<td>Footer 2</td>
</tr>
</tfoot>
</table>
<div id="testContainer">TEST CONTAINER</div>
</body>
</html>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为你的问题是
scrollTo
使用animate
:并且
animate
使用计时器来执行动画。结果是.scrollTo
将在滚动完成之前返回,并且您将在scrollTo
仍在滚动时重新绑定滚动处理程序。因此,就会发生你意想不到的事件。一个简单的解决方案是使用一个标志来告诉
makeVisibleWhatMust
scrollTo
正在滚动,并在完成时使用scrollTo
回调来清除该标志,像这样:这是一个似乎可以工作的实时版本: http://jsfiddle.net/ambiguously/ZEx6M/1/
I think you're problem is that
scrollTo
usesanimate
:And
animate
uses a timer to perform the animation. The result is that.scrollTo
will return before the scrolling has completed and you'll rebind your scroll handler while thescrollTo
is still scrolling. Hence the events when you're not expecting them.An easy solution would be to use a flag to tell
makeVisibleWhatMust
thatscrollTo
is scrolling and use ascrollTo
callback to clear the flag when it is done, something like this:And here's a live version that seems to work: http://jsfiddle.net/ambiguous/ZEx6M/1/