jQuery: fadeOut().empty().append(...).fadeIn()在第一次使用时无法正常工作

8

我很难理解为什么会出现我看到的行为。我有一段代码,旨在淡出一个容器,替换其内容,然后在完成后再淡入它。

我使用jQuery,所以代码看起来像这样:

var transitionToNewContent = function(container, new_content) {
    container.fadeOut().delay(1000).empty().append(new_content).fadeIn();
};


transitionToNewContent($('#id'), "<p>magic</p>");

第一次单击激活此转换的链接时,内容会立即被替换,然后淡出发生,然后再次淡入。
之后每次单击链接时,我看到正确的行为:淡出,然后使用新内容淡入。
有任何想法为什么会发生这种情况?
我附上一个完整的HTML文件,其中显示了该行为:
我对jQuery相当陌生,正在尝试以“正确的方式”进行操作。有关样式的任何注释都将不胜感激。
<doctype html>
<html>
<head>
  <style type="text/css">
    #main_container {
    width: 800px;
    margin-left: auto;
    margin-right: auto;
    margin-bottom: 3em;
    margin-top: 0;
    height: 100%;
    position: relative;
    top: 0px;
    bottom: 0px;
}

#loading {
    float: right;
    position: relative;
    top: 10px;
    left: 10px;
    z-index: 1;
}

#sidebar {
    float: left;
    width: 240px;
    border: #078600 1px dashed;
    position: relative;
    top: 10px;
    left: -250px;
    margin-right: 20px;
    background: #cccccc;
    z-index: 1;
    padding: 10px;
    font-size: 0.65em;
    display: none;
}

#main_content {
    z-index: 0;
    position: absolute;
    top: 0px;
    left: 5px;
    width: 100%;
    height: 100%;
    float: right;
    background: white;
    padding-top: 0;
    padding-bottom: 3em;
    padding-left: 20px;
    border-right: 1px dotted #078600;
    border-left: 1px dotted #078600;
    border-top: 3px solid white;
}

  </style>
  <link rel="stylesheet" type="text/css" href="/main.css" />
</head>
<body>
  <div id="main_container">
    <div id="sidebar"><h1>Sidebar</h1><p>some text</p></div>
    <div id="loading" style="display: none">&nbps;</div>

    <div id="main_content">
      <h1 id="page_title">Title</h1>
      <div id="page_content"><h2>heading</h2><p>Some testing text</p></div>
    </div>
  </div>
  <script type="text/javascript">
var include = function(src) {
    document.write('<script type="text/javascript" src="' + src + '"></scr' + 'ipt>'); 
};

include("http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js");
include("http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.min.js");

var bootStrapSites = function() {
    var sideBar = $('#sidebar');
    sideBar.delay(1000).fadeIn();
    loadSiteList(sideBar);
};

var transitionToNewContent = function(container, new_content) {
    container.fadeOut().delay(1000).empty().append(new_content).fadeIn();
};

var editSite = function(site) {
    transitionToNewContent($('#page_content'), "<p>This is where the magic will happen</p>");
};

var loadSiteList = function(container) {
//    $.getJSON("/sites/list.json", function(data) {

            var data = $.parseJSON('[{"id": "1", "name": "cool name"}]');
        container.empty(container);
        container.append("<h2>new heading</h2>");
        container.append("<ul id='sitesList'></ul>");

        var sitesList = $('#sitesList');
        $.each(data, function(idx, site) {
            var id = 'show_site_id_' + site._id;
            sitesList.append("<li><a id='" + id + "' href='#'>" + site.name + "</a></li>");
            $('#' + id).click(function() {
                editSite(site);
            });
        });
//  });
};
</script>
  <script type="text/javascript">

$(document).ready(function() {
   bootStrapSites();
});

  </script>
</body>
</html>

不,只需要一个虚构的id值和该id上的有效选择器。 - Pieter Breed
1
不要这样写,你应该先写一个美元符号,然后是一个点,最后是一个括号。 - JAAulde
2个回答

31

问题在于jQuery中有两种不同类型的函数——立即生效的函数和将效果添加到效果队列中的函数。

让我们来看一下您的代码:

container.fadeOut().delay(1000).empty().append(new_content).fadeIn();
  • fadeOut 将淡出操作添加到队列中。
  • delay 将延迟添加到队列中。
  • empty 立即清空元素。
  • append 立即将内容添加到元素中。
  • fadeIn 将淡入操作添加到队列中。

将项目添加到队列的函数会立即返回--它们在完成之前不会等待生效。这意味着所有函数(几乎)同时被调用--它们不会等待动画函数完成。

你需要使用fadeOut 的回调参数来实现:

container.fadeOut(1000, function(){
    container.empty().append(new_content).fadeIn();
});

当淡出操作完成时,该函数被触发,因此清空和添加操作被延迟直到元素被隐藏。


2

您需要使用回调函数来获得您所需要的效果。

var transitionToNewContent = function(container, new_content) {
    container.fadeOut(1000, function(){
         $(this).empty().append(new_content).fadeIn();
    });
};

这确保了容器在动画完成后才被替换。

这个可以运行,有没有办法确保fadeOut(1000, ...)中的魔数(1000)与fadeOut()的默认值相同? - Pieter Breed
1
我相信所有动画的默认值都是“快速”= 200,因此如果您想使用默认值,可以将字符串“快速”替换为1000。请参阅:http://api.jquery.com/fadeOut/ - Mark Brown
1
或者您可以完全省略参数:container.fadeOut(fn) 使用默认速度(实际上是400毫秒)。 - lonesomeday
2
抱歉这么晚才提出来,但对于那些访问此处的人,.promise().done是一种使用更少且更易理解的代码进行操作的另一种方式。只需调用要操作的对象的 .promise().done(function(){}),并将要运行的代码放在函数内部即可。它将仅在该对象的所有效果队列运行完毕后才会运行。 - Hallaghan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接