与jQuery Mobile的AJAX调用 - 为什么方法被调用两次?

问题描述:

我正在撕掉我的头发。我是jQuery Mobile的新手,当浏览器滚动到页面底部时,我有一个可以加载新内容的函数。与jQuery Mobile的AJAX调用 - 为什么方法被调用两次?

我也有一个<select>在哪里你可以选择类别。它在起始页面上工作正常(即没有选择类别)。但是,只要我选择一个类别,然后滚动到底部,功能bindScroll()就会触发两次。

我一直在为此工作近两天,试图找到一些解决方案,但没有。我还没有真正弄清楚不同的jQuery Mobile事件,因此可能存在一些问题。

请看我的代码和帮助,如果你可以。该网站建立在.NET MVC中,但问题在于jQuery。

@using Namespace.Helpers 
@{ 
    ViewBag.Title = "Home Page"; 
} 
<!-- Get a drop down of the different categories --> 
@Html.Raw(Html.GetCategories(true, "CategoryId", 0, true)) 

<!-- list view to append the fetched ads to --> 
<ul data-role="listview" data-inset="true" id="ad-list"> 

</ul> 

<script> 
    // keeps track of how many rows to skip in the db. this is passed along to the server side 
    var currentPos = 0; 

    // save the categoryId 
    var categoryId = $('#CategoryId').val(); 

    $('#page-start').live('pagecreate', function() { 

     // load the ads for the first call 
     loadAds(); 


     //handle the category drop down 
     $('#CategoryId').change(function() { 
      // clear the list of ads 
      $('#ad-list').empty(); 

      // reset so we start fetching from the first row in the db, used on server side 
      currentPos = 0; 

      // update the category value to pass along to the server 
      categoryId = $('#CategoryId').val(); 

      // just to know that it has a value 
      console.log(categoryId); 

      // re-load the new ads 
      loadAds(); 

     }); 


    }); 

    // method that loads ads via AJAX 
    function loadAds() { 
     console.log('loadAds()'); 
     $.ajax({ 
      // method on the server that returns a partial view 
      url: '/Home/LoadMoreAds', 
      type: 'GET', 
      data: { 
       // pass along some data 
       currentPosition: currentPos, 
       categoryId: categoryId 
      }, 
      success: function (result) { 
       // add the result to the ad-list 
       $('#ad-list').append(result); 
       $('#ad-list').listview('refresh'); 

       // once again, bind the scroll event 
       $(window).scroll(bindScroll); 

      }, 
      error: function (data, textStatus, jqXHR) { 
       alert(textStatus); 
      } 

     }); 

    } 

    // method that checks if the scroll is near the bottom of the page 
    function bindScroll() { 
     if($(document).height() > $(window).height()) 
     { 
      if ($(window).scrollTop() + $(window).height() > $(document).height() - 100) { 
       $(window).unbind('scroll'); 

       // just to know that the method has run 
       console.log('bindScroll()'); 

       // update counter to skip the already loaded rows 
       currentPos++; 

       // load new ads 
       loadAds(); 

      } 
     } 
    } 

</script> 

编辑答案: -------------------------------------- ---------

我从Mike C的建议去绑定和重新绑定滚动事件。页面初始化时只有一个绑定。 然后我用这个代码:

// method that checks if the scroll is near the bottom of the page 
    var scrollHappening = false; 
    function bindScroll() { 
     if (scrollHappening) { 
      return false; 
     } else { 
      if ($(document).height() > $(window).height()) { 
       if ($(window).scrollTop() + $(window).height() > $(document).height() - 100) { 

        // just to know that the method has run 
        console.log('bindScroll()'); 

        // update counter to skip the already loaded rows 
        currentPos++; 

        // load new ads 
        loadAds(); 

        scrollHappening = true; 

       } 
      } 
     } 
    } 

而在Ajax调用的success:设置scrollHappening = false。似乎工作相当不错!

选择一个类别后,您在此位置重新绑定bindScroll,因此它会被调用两次!即当你选择一个类别,你做()调用LoadAds其中有这样的:

success: function (result) { 
        // add the result to the ad-list 
        $('#ad-list').append(result); 
        $('#ad-list').listview('refresh'); 

        // once again, bind the scroll event 
        $(window).scroll(bindScroll); 

       }, 

每次调用LoadAdds(),这个函数增加了一个额外的事件调用bindscroll。

  1. LoadAdds()你现在有1级的事件势必在滚动滚动页面 - > bindscroll == 1个事件势必
  2. LoadAdds()现在有2个事件势必 所以滚动 - > bindscroll == 2事件绑定

当您实际上滚动时,如果您有2个事件绑定到bindscroll,它会在解除绑定发生之前调用这两个事件是我的猜测。

我认为你真正的解决方法是不绑定和解绑。绑定一次,不要使用bind/unbind来玩这个游戏。修改您的代码以使用单个绑定。在底部,有一个变量来标记你是否已经在底部,如果你是在退出函数。或类似的东西。这个绑定/解绑绑业务让您头疼。

+0

感谢您的努力,但这不利于我们。奇怪的是,滚动事件不应该重新绑定,直到ajax成功的方法,但不知何故它被触发。另外奇怪的是,它只出现在我选择了一个类别时,否则它运行平稳。 – 2013-02-28 14:10:58

+0

啊,你为什么不这么说!现在看来更加明显。我编辑了我的答案。 – 2013-02-28 14:15:10

+0

我不明白。这与原始代码完全相同。 当bindScroll()运行时,我取消绑定滚动并加载广告,并且在广告加载到列表中后,我重新绑定滚动。或者至少这是我的意图。让我生气的是,当我显示“所有类别”时它工作正常。 – 2013-02-28 15:24:50