2

我正在使用以下 jQuery 代码片段来执行 AJAX 请求:

$.ajax({
    url: page,
    context: $(pageContent),
    beforeSend: function(){
        $(pageContent).css('opacity', '0');
    },
    success: function(html){
        $(pageContent).html(html);
    },
    complete: function(){
        $(pageContent).css('opacity', '1');
    }
});

我还设置了 CSS3 过渡,以便不透明度的变化在 0.25 秒内淡入淡出。期望的结果是(单击链接后)页面的一部分淡出,然后内容被替换,最后该部分再次淡入(显示新内容)。

问题是在淡出转换完成之前内容被 Ajax 答案替换。

你会怎么做才能让 AJAX 请求仅在 CSS3 转换完成后启动?


阅读不同的线程让我考虑了这个解决方案:

box.addEventListener( 
     'transitionEnd', 
     function( event ) { 
         alert( "Finished transition!" ); // here I could launch my Ajax request
     }, false );

我只能在淡出完成时使用这样的东西来启动 ajax 请求,但是:

  • 它涉及处理 $.ajax 方法之外的第一个转换(因此删除了 beforeSend 方法)
  • 我不知道如何只听不透明过渡
  • 对我来说,ajax 请求是由转换触发的,因为它当前是由单击链接触发的。

我还查看了 jQuery animate 函数,但它似乎没有使用 CSS3 过渡。

任何帮助将非常感激

4

3 回答 3

-1

我发现 $.Deferred 是解决这个问题的最佳方法。我不会过多介绍它的工作原理,而只是解释其好处和解决方案。

这是文档。 http://api.jquery.com/category/deferred-object/ 我发现这是开始使用 $.Deferred 的绝佳资源。 http://www.html5rocks.com/en/tutorials/async/deferred/

所以基本上你想将 CSS3 动画与异步的 ajax 请求结合起来。然而,您想使用回调以使效果同步或协调,即在新元素中淡出 ajax 中的某些元素,然后将其淡入。使用 $.Deferred 的优点是您可以更协调地协调这些事件“复杂的?” 方法。而不是淡出然后执行ajax请求然后淡入,这没关系,但这意味着您必须等待动画完成才能开始请求。使用 $.Deferred 您可以执行诸如淡出和触发 ajax 请求之类的操作,并且当它们都完成淡入时。

这是一个工作小提琴。

http://jsfiddle.net/SB987/1/

我将通过下面的js部分发表评论。

//Clicking the anchor triggers the loadContent function
$('a').on('click', function(){
    var url     =   $(this).data('url');
    var target  =   $(this).data('target');
    loadContent(url, target);
});

//Slide out the existing element using a css transform
var slideOut = function($el, $target){
    //Create a deffered object
    var deferred = new $.Deferred();
    //Slide our element out (note this has a transition through css) (double note you should use transforms for other browsers
    $el.css({"-webkit-transform":"translateX(100%)"}).on('transitionend webkitTransitionEnd', function(e){
       //once the transition ends resolve our deferred object and return $target
       deferred.resolve($target);
    });
    //return the promise from the deferred object
    return deferred.promise();
};

//Add the element returned from our Ajax request and slide it in
var slideIn = function(el, $target){
    var $el = $(el);
    $target.empty().append($el).css({height : "auto"});
    //weird bug, css transition doesn't work when taken out of setTimeout (any ideas?)
    setTimeout(function(){
        $el.removeClass('content2');
    }, 0);
};


//Make an ajax request and returns some html
//Note ajax requests return promises as well as deferred objects, I am just wrapping it here for clarity
var getData = function(url){
    var deferred = new $.Deferred();
    //var htmlData = "asdfasfasdf";
    $.ajax({
        url: url,
        method : "POST",
        data : { 'html': htmlData},
         success: function (returnhtml) {
             //resolve our deferred object and return the response
             deferred.resolve(returnhtml);
         },
         error: function (xhr, ajaxOptions, thrownError) {
             //you can reject a deferred object and then execute a different callback(s) but i'll let you figure that out
             deferred.reject(thrownError);
         }
    });
    //return the promise from the deferred object
    return deferred.promise();
}


var loadContent = function(url, target){
    $el = $('.content');
    $target = $(target);
    //Run slideOut and getData
    var slidePromise = slideOut($el, $target);
    var dataPromise = getData(url);
    //So because we are returning promises from deferred objects in both of the above functions the following code will only run once those deferred objects have been resolved
    $.when(slidePromise, dataPromise).done(function(slidePromise, dataPromise) {
        //Great the ajax request is finished and our slideOut animation has finished, lets slide in the new content passing it the target element and response content
        slideIn(dataPromise, slidePromise );
    });
};
于 2014-03-28T19:49:37.130 回答
-1

如果您愿意为 jquery animate 放弃过渡:

$(pageContent).animate({'opacity': '0'},250,
   function(){
      $.ajax({
          url: page,
          context: $(pageContent),
          success: function(html){
              $(pageContent).html(html);
          },
          complete: function(){
              $(pageContent).animate({'opacity': '1'},250);
          }
      });
   });

没有测试它,所以如果语法略有偏差,对不起。虽然给你的想法。一旦动画到 0 不透明度完成,就会进行 ajax 调用。

于 2011-05-06T00:17:15.660 回答
-1

使用 css3-transitions 创建几个 css 类,并在成功/错误/完成回调中使用 .addClass/removeClass

http://css3.bradshawenterprises.com/transitions/ — 尽管初始状态是可以接受的,这就是为什么您可以完全异步使用它们的原因。

于 2011-08-16T01:54:14.393 回答