是什么可以使jQuery的取消绑定功能无法按预期工作? [英] What can make jQuery's unbind function not work as expected?

查看:67
本文介绍了是什么可以使jQuery的取消绑定功能无法按预期工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

查看以下代码(此外,您将需要 jquery. js jquery.viewport.js jquery. scrollTo.js ).

Have a look at the following code (additionally, you will need jquery.js, jquery.viewport.js and jquery.scrollTo.js).

该脚本的行为是,每当我滚动页面时,红色行(类别为alwaysVisible<tr>元素)都应插入最顶部可见行(<tr>元素)的下面.那张桌子的然后,应滚动页面,以使这些红色行中的第一个恰好"显示在视口顶部.实际上发生的是makeVisibleWhatMust();被重复调用,直到到达页面末尾.我以为$(window).unbind('scroll');可以阻止makeVisibleWhatMust();再次被调用,但是显然这是行不通的.

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.

有什么想法吗?

这是我写的JavaScript:

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);
  }
);

这是要在其上进行测试的HTML页面:

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>

推荐答案

我认为您的问题是 scrollTo 使用 animate :

I think you're problem is that scrollTo uses animate:

// From the plugin's source
function animate( callback ){  
    $elem.animate( attr, duration, settings.easing, callback && function(){  
        callback.call(this, target, settings);  
    });  
};

animate使用计时器执行动画.结果是.scrollTo将在滚动完成之前返回,并且您将在scrollTo仍在滚动时重新绑定滚动处理程序.因此,当您不期望发生这些事件时.

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 the scrollTo is still scrolling. Hence the events when you're not expecting them.

一个简单的解决方案是使用一个标志来告知makeVisibleWhatMust scrollTo正在滚动,并使用scrollTo回调在完成后清除该标志,如下所示:

An easy solution would be to use a flag to tell makeVisibleWhatMust that scrollTo is scrolling and use a scrollTo callback to clear the flag when it is done, something like this:

function makeVisibleWhatMust() {
  // Ignore the event if we're doing the scrolling.
  if(makeVisibleWhatMust.isScrolling)
    return;
  $('#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] );
      });
      makeVisibleWhatMust.isScrolling = true;
      $(window).scrollTo($('tr.alwaysVisible')[0], {
        onAfter: function() { makeVisibleWhatMust.isScrolling = false; }
      });
    }
  );
}
makeVisibleWhatMust.isScrolling = false;

这是一个似乎可行的实时版本: http://jsfiddle.net/ambiguous/ZEx6M /1/

And here's a live version that seems to work: http://jsfiddle.net/ambiguous/ZEx6M/1/

这篇关于是什么可以使jQuery的取消绑定功能无法按预期工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆