AppendChild将所有新元素添加到循环中的最后一个元素。为什么?

时间:2015-04-28 13:48:46

标签: javascript html ajax

我循环播放了一组div,这些div为YouTube视频获取并显示其标题,说明等。我循环播放的div看起来像这样:

<div class="tutorialVideoDataContainer" data-clipid="xxxxxxxxxxx"></div>
<div class="tutorialVideoDataContainer" data-clipid="xxxxxxxxxxx"></div>
<div class="tutorialVideoDataContainer" data-clipid="xxxxxxxxxxx"></div>
<div class="tutorialVideoDataContainer" data-clipid="xxxxxxxxxxx"></div>
<div class="tutorialVideoDataContainer" data-clipid="xxxxxxxxxxx"></div>

由于某种原因,循环将所有信息添加到这些div中的最后一个,而不是将信息应用于循环内的当前div。知道为什么会这样吗?

而且,作为一个子问题,为什么我不能在ajax呼叫中到达我?我必须设置tutorial = tutorials [i]并将孩子们附加到教程而不是教程[i],但我不能在ajax部分中使用教程[i]。我无法理解其中的区别。

(function () {
    var tutorials = document.getElementsByClassName('tutorialVideoDataContainer');

    for (var i = 0; i < tutorials.length; i++) {
        var tutorial = tutorials[i];

        console.log(i);
        console.log(tutorial);
        console.log(tutorials[i]);

        var id = tutorial.getAttribute('data-clipid');

        $.ajax({
            url: "http://gdata.youtube.com/feeds/api/videos/" + id + "?v=2&alt=json",
            dataType: "jsonp",
            success: function (data) {
                var title = data.entry.title.$t;
                var description = data.entry.media$group.media$description.$t;
                var duration = data.entry.media$group.media$content[0].duration;
                var thumbnail = data.entry.media$group.media$thumbnail[3].url;

                if (title.length > 0) {
                    var titleElement = document.createElement("h3");
                    titleElement.innerText = title;
                    tutorial.appendChild(titleElement);
                }

                if (description.length > 0) {
                    var descriptionElement = document.createElement("p");
                    descriptionElement.innerText = description;
                    tutorial.appendChild(descriptionElement);
                }

                var minutes = Math.floor(duration / 60);
                var seconds = duration - minutes * 60;

                var durationElement = document.createElement("p");
                durationElement.innerText = minutes + ":" + seconds;
                tutorial.appendChild(durationElement);

                var clickLink = document.createElement("a");
                clickLink.className = "showOverlayVideo";

                var thumbnailElement = document.createElement("img");
                thumbnailElement.src = thumbnail;
                thumbnailElement.alt = title;
                clickLink.appendChild(thumbnailElement);

                tutorial.appendChild(clickLink);
            }
        });
    }
})();

3 个答案:

答案 0 :(得分:2)

如果你遍历数组和crate闭包你访问数组的索引,你访问变量的引用而不是它的副本,所以当所有异步代码完成时你最终会引用最后一个元素。要修复它,您需要使用新引用创建另一个闭包:

for (var i = 0; i < tutorials.length; i++) {
    (function(tutorial) {
        // you can use tutorial inside
    })(tutorials[i]);
}

答案 1 :(得分:0)

由于javascript事件循环的工作方式,循环在ajax请求返回之前完成运行。因此,当他们这样做时,变量教程被设置为循环中的最后一个。

从youtube api返回的数据是否包含剪辑ID,然后您可以使用它来在回调中而不是在循环内查找正确的dom元素。

答案 2 :(得分:0)

我的猜测是,因为$.ajax()不是阻塞函数,所以循环在ajax完成之前就完成了。这将导致执行路径看起来像这样:

  1. 循环开始,i = 0
  2. 进行Ajax调用
  3. i = 1
  4. i = 2
  5. ...
  6. i = tutorials.length
  7. Ajax调用结束
  8. 希望有帮助/有意义。