目前的答案都没有解决真正的问题,所以我会试一试。
var datahtml = "<html><body><div class=\"class0\"><h4>data1</h4><p class=\"class1\">data2</p><div id=\"mydivid\"><p>data3</p></div></div></body></html>";
console.log($(datahtml));
$(datahtml)
div.class0
是一个仅包含元素的 jQuery 对象,因此当您调用.find
它时,您实际上是在寻找后代div.class0
而不是您期望的整个 HTML 文档。
一个快速的解决方案是将解析的数据包装在一个元素中,以便.find
按预期工作:
var parsed = $('<div/>').append(datahtml);
console.log(parsed.find(".class0").text());
小提琴
这样做的原因不是很简单,但我假设 jQuery 通过简单地将 HTML 字符串放入单独的动态创建 DOM 片段然后检索解析的元素来“解析”更复杂的 html 字符串,此操作很可能会使 DOM 解析器忽略html
andbody
标记,因为在这种情况下它们是非法的。
这是一个非常小的测试套件,它证明了这种行为在 jQuery 1.8.2 一直到 1.6.4 都是一致的。
编辑:引用这篇文章:
问题是 jQuery 创建了一个 DIV 并设置innerHTML
然后获取 DIV 子元素,但由于 BODY 和 HEAD 元素不是有效的 DIV 子元素,因此浏览器不会创建这些元素。
让我更加确信我的理论是正确的。我会在这里分享它,希望它对你有一些意义。将 jQuery 1.8.2 的未压缩源与此放在一起。#
表示行号。
所有通过(定义@#6122)生成的文档片段都将通过(#6151)(即使它是一个缓存的片段,它在创建时已经通过),并且正如上面引用的文本所暗示的那样,(定义@# 6275)在安全片段内创建一个新的作为已解析数据的容器 -在 #6301-6303 创建的元素,在 #6344 检索,在 #6347 删除 div 以进行清理(加上 #6359-6361 作为错误修复),在#6351-6355 处合并到返回数组中并在#6406 处返回。jQuery.buildFragment
jQuery.clean
jQuery.clean
jQuery.clean
div
div
childNodes
childNodes
因此,所有调用 的方法jQuery.buildFragment
,其中包括jQuery.parseHTML
和jQuery.fn.domManip
- 其中包括.append()
,.after()
,.before()
它们调用 domManip
jQuery 对象方法,以及$(html)
在jQuery.fn.init
(定义 @#97,处理复杂 [多个单个标签] html 字符串 @#125 , 调用jQuery.parseHTML
@#131)。
几乎所有 jQuery HTML 字符串解析(除了单标签 html 字符串)都是使用div
元素作为容器完成的,并且html
/body
标签不是div
元素的有效后代,因此它们被剥离是有道理的。
附录:较新版本的jQuery(1.9+)已经重构了HTML解析逻辑(例如,内部jQuery.clean
方法不再存在),但整体解析逻辑保持不变。