jQuery非常奇怪的行为 - 输出html与追加的顺序不一样

时间:2011-07-02 10:47:19

标签: jquery html dom append

我有一个刷新元素队列的函数 - 每个元素必须用div表示,但效果对我来说是总WTF。这是功能:

this.refreshQueue = function( ) {
    $("#queue").html('');
    for( var id in self.queue ) {
        console.log('Opening div');
        $("#queue").html( $("#queue").html()+'<div class="queueelement">');
        self.appendUser( self.queue[id].data );
        console.log('Closing div');
        $("#queue").html( $("#queue").html()+'</div>');
    }
} 

this.appendUser = function( data ) {
    console.log('Appending h4');
    $("#queue").html( $("#queue").html()+'<h4>'+data.login +'</h4>' );
}

我在firebug日志中看到了:

Opening div
Appending h4
Closing div

没关系,但在该操作之后的HTML看起来像这样:

<div class="queueelement"></div>
<h4>Somelogin</h4>

而不是:

<div class="queueelement">
<h4>Somelogin</h4>
</div>

任何想法是什么导致了这个?

早期我尝试过.append() - 效果相同。

5 个答案:

答案 0 :(得分:4)

请参阅documentation

  

此方法使用浏览器的innerHTML属性。

您无法设置开始标记,稍后会添加结束标记。浏览器通过自动添加结束标记来更正开始标记。

您不仅要设置HTML(作为文本),还要解析它并创建DOM元素并将其插入树中。为了解析,HTML必须是正确的。

您使用的任何方法都会发生这种情况。您也可以在控制台中尝试:

> d = document.createElement('div');
  <div>​</div>​
> d.innerHTML = '<span>';
  "<span>"
> d.innerHTML += 'foo';
  "<span></span>foo"
> d.innerHTML += '</span>';
  "<span></span>foo</span>"
> d.innerHTML
  "<span></span>foo"

您必须构建整个字符串并立即插入。

答案 1 :(得分:3)

问题在于您尝试将HTML放入DOM中,就好像它是HTML文档一样。当浏览器读取HTML页面时,它会将其转换为DOM结构。这是一个相关节点的树状系统。它与原始HTML有一些相似之处,可以序列化到它,但你不能只是向它添加HTML,并期望它像在原始文档中添加内容一样工作。

$("#queue").html( $("#queue").html()+'<div class="queueelement">');

这表示“在HTML的末尾添加div节点”。由于每个节点必须关闭或自动关闭,浏览器会自动关闭它。

稍后添加</div>时,它是荒谬的 - 结束标记本身不存在,因此会被忽略。

解决方案是将所有HTML添加到一起并一次性插入,或修改div中的appendUser元素。

答案 2 :(得分:2)

我认为您必须立即构建一个字符串并输出到html,而不是使用.html()插入未完成的元素。

这样的事情:

    this.refreshQueue = function () {
        var output = "";
        for (var id in self.queue) {
            output += "<div class=\"queueelement\">";
            output += appendUser(self.queue[id].data);
            output += "<\div>";
        }
        $("#queue").html(output);
    }

    this.appendUser = function (data) {
        return "<h4>" + data.login + "</h4>";
    }

答案 3 :(得分:1)

html()自动关闭所有未关闭的代码。因此,当您尝试添加更多html时,它已关闭div。为什么不使用wrap()

self.appendUser( self.queue[id].data ).wrap($('<div />').addClass('queueelement')).parent().appendTo($("#queue"));

你有这个函数本身只返回$('<h4 />)'元素

答案 4 :(得分:1)

您还可以将标记放入其自己的变量中,然后将内部字符串添加到该div变量,然后将其附加到容器div。

    var div = $("<div class='elem'></div>");
    div.append("<h4>Some Login</h4>");

    $("#out").append(div);

http://jsfiddle.net/Gz3qR/