getElementsByClassName 返回 [] 而不是异步附加节点

发布于 2024-12-07 07:58:58 字数 1392 浏览 1 评论 0原文

(在第一个问题被严重阐述后,我再次提出我的问题)

我面临以下问题:

<div class="testA" id="test1"></div>

上面的书面元素是预定义的。我现在通过 XMLHttpRequest & 加载 xml 树Co. 提供以下响应:

<response>
    <div class="colorSelector" id="0-0">
        <div class="gbSelector" id="1-0">
            <table style="none" id="2-0"></table>
        </div>
    </div>
</response>

我现在将第一个 div 使用附加

request.responseXML.getElementsByTagName("response")[0]
                       .getElementsByTagName("div")[0]

到预定义的 div

<div class="testA" id="test1">

最终文档如下所示(使用开发工具检查)

<div class="testA" id="test1">
    <div class="colorSelector" id="0-0">
        <div class="gbSelector" id="1-0">
            <table style="none" id="2-0"></table>
        </div>
    </div>
</div>

:我现在尝试使用 getElementById("0-0") 获取元素

我得到了预期结果。

但使用 getElementsByClassName("colorSelector") 返回 []

我错过了什么吗?这可能是节点类型为 Element 而不是 HTMLElement 的事实遗留下来的吗?

(I ask my question again after the first one was terribly formulated)

I face the following problem:

<div class="testA" id="test1"></div>

The above written element is predefined. I now load a xml tree via XMLHttpRequest & Co. delivering the following response:

<response>
    <div class="colorSelector" id="0-0">
        <div class="gbSelector" id="1-0">
            <table style="none" id="2-0"></table>
        </div>
    </div>
</response>

I now append the first div using

request.responseXML.getElementsByTagName("response")[0]
                       .getElementsByTagName("div")[0]

into the predefined div

<div class="testA" id="test1">

The final document looks like this (checked using development tools):

<div class="testA" id="test1">
    <div class="colorSelector" id="0-0">
        <div class="gbSelector" id="1-0">
            <table style="none" id="2-0"></table>
        </div>
    </div>
</div>

When I now try to get the element <div class="colorSelector" id="0-0"> using getElementById("0-0") I get the expected result.

But using getElementsByClassName("colorSelector") returns [].

Did I miss something? Is it probably a leftover of the fact the nodes were of type Element and not HTMLElement?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

夜血缘 2024-12-14 07:58:59

请描述您正在对返回的结果执行什么操作。 nodeList 和节点之间有一个显着的区别,nodeList 是LIVE

因此,如果您将 getElementsByClassName() (或类似)返回的 nodeList 分配给一个变量,则当您从 DOM 中删除 nodeList 内的节点时,该变量将会更改。

Please describe what you are doing with the returned results. There is a significant difference between a nodeList and a node, nodeLists are LIVE.

So if you assign a nodeList returned by getElementsByClassName() (or similar) to a variable, this variable will change when you remove the nodes inside the nodeList from the DOM.

梦在深巷 2024-12-14 07:58:59

我现在附加第一个 div

你是怎么做的? responseXML 中的内容是 XML 元素,而不是 HTML 元素。

  • 您不应该能够将它们appendChild到非XHTML HTML文档中;

  • 实际上你根本不应该能够将它们appendChild到另一个文档中,你应该使用importNode将元素从一个文档获取到另一个文档,否则你应该得到 WRONG_DOCUMENT_ERR;

  • 即使由于浏览器不严格而设法将它们插入到 HTML 中,它们仍然是 XML 元素,而不是语义上的 HTML 元素。因此,class 属性没有什么特别之处;仅具有该名称并不能使该属性真正代表一个类。 getElementsByClassName 不会仅仅因为元素具有 name class 属性而返回它们;它们必须是其语言定义将属性与类概念(通常意味着 HTML、XHTML 或 SVG)相关联的元素。

(对于 id 属性来说也是如此;仅仅拥有一个名为 id 的属性并不能使其在概念上成为 ID。因此 getElementById 不应该起作用。有一种方法可以通过使用 将任意 XML 属性与 ID 相关联,而您无法通过类来获得这种属性。 > 文档类型中的声明通常不值得费心。不过,在支持 XML ID 的实现中,xml:id 也是一种特殊情况。)

如果您使用本机 XHTML 页面,则可以通过放置合适的 xmlns 来使其工作。内容上的 code> 属性使其成为实际的 XHTML 而不仅仅是任意的 XML,然后使用 importNode。但总的来说,这是不值得的;返回 HTML 标记字符串(通常为 JSON)或原始 XML 数据往往更简单,客户端脚本可以从中构造 HTML 元素本身。

I now append the first div

How do you do that? What you have in the responseXML are XML elements, and not HTML elements.

  • You shouldn't be able to appendChild them into a non-XHTML HTML document;

  • actually you shouldn't be able to appendChild them into another document at all, you're supposed to use importNode to get elements from one document to another, otherwise you should get WRONG_DOCUMENT_ERR;

  • even if you managed to insert them into an HTML due to browser laxness, they're still XML elements and are not semantically HTML elements. Consequently there is nothing special about the class attributes; just having that name doesn't make the attribute actually represent a class. getElementsByClassName won't return elements just because they have attributes with the name class; they have to be elements whose language definition associates the attributes with the concept of classness (which in general means HTML, XHTML or SVG).

(The same should be true of the id attributes; just having an attribute called id doesn't make it conceptually an ID. So getElementById shouldn't be working. There is a way to associate arbitrary XML attributes with ID-ness, which you don't get with class-ness, by using an <!ATTLIST declaration in the doctype. Not usually worth bothering with though. Also xml:id is a special case, in implementations that support XML ID.)

You could potentially make it work if you were using a native-XHTML page by putting suitable xmlns attributes on the content to make it actual-XHTML and not just arbitrary-XML, and then using importNode. But in general this isn't worth it; it tends to be simpler to return HTML markup strings (typically in JSON), or raw XML data from which the client-side script can construct the HTML elements itself.

动听の歌 2024-12-14 07:58:58

colorSelector 被注释掉。 JavaScript 只能在 DOM 中工作,注释掉的部分不在 DOM 中。

colorSelector is commented out. JavaScript only works within the DOM, and commented out portions aren't in the DOM.

小猫一只 2024-12-14 07:58:58

既然您说您的 getElementById("0-0") 成功,那么显然您实际上并没有注释掉节点。

我猜你正在做:

document.getElementById("0-0").getElementsByClassName('colorSelector');

...这不会起作用,因为 ID 选择的元素没有该类的任何后代。


由于您在标记中显示 HTML 注释,我还想知道页面上是否有一些 ID 为 "0-0" 的不同元素。看看那个。


如果您的节点实际上被注释掉,您需要首先选择注释,并将其替换为内部包含的标记:

var container = document.getElementById('test1'),
    comment = container.firstChild;

while( comment && comment.nodeType !== 8 ) {
    comment = comment.nextSibling;
}

if( comment ) {
    container.innerHTML = comment.nodeValue;
}

...导致:

<div class="testA" id="test1">
    <div class="colorSelector" id="0-0">
        <div class="gbSelector" id="1-0">
            <table style="none" id="2-0"></table>
        </div>
    </div>
</div>

...但是,这似乎不太可能,因为您的 getElementsById 确实有效。

Since you said that your getElementById("0-0") is successful, then clearly you don't actually have the nodes commented out.

I'm guessing you're doing:

document.getElementById("0-0").getElementsByClassName('colorSelector');

...which will not work because the element selected by ID does not have any descendants with that class.


Since you show HTML comments in the markup, I'd also wonder if you have some different element on the page with the ID "0-0". Take a look for that.


If your nodes are actually commented out, you'll need to first select the comment, and replace it with the markup contained inside:

var container = document.getElementById('test1'),
    comment = container.firstChild;

while( comment && comment.nodeType !== 8 ) {
    comment = comment.nextSibling;
}

if( comment ) {
    container.innerHTML = comment.nodeValue;
}

...resulting in:

<div class="testA" id="test1">
    <div class="colorSelector" id="0-0">
        <div class="gbSelector" id="1-0">
            <table style="none" id="2-0"></table>
        </div>
    </div>
</div>

...but there again, this doesn't seem likely since your getElementsById does work.

如梦亦如幻 2024-12-14 07:58:58

这是针对 Firefox、Opera、Chrome 和 Safari 的一种方法。基本上,您只需执行 div.innerHTML = div.innerHTML 将其内容重新解释为 HTML,这将使 XML 文件中的该类属性被视为 HTML 类名。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title></title>
        <script>
            window.addEventListener("DOMContentLoaded", function() {
                var div = document.getElementsByTagName("div")[0];
                var req = new XMLHttpRequest();
                req.onreadystatechange = function() {
                    if (this.readyState === 4 && this.status === 200) {
                        var doc = this.responseXML;
                        div.appendChild(document.importNode(doc.getElementsByTagName("response")[0].getElementsByTagName("div")[0], true));
                        div.innerHTML = div.innerHTML;
                        alert(document.getElementsByClassName("colorSelector").length);
                    }
                };
                req.open("GET", "div.xml");
                req.send();
            }, false);
        </script>
    </head>
    <body>
        <div class="testA"></div>
    </body>
</html>

如果您在本地支持 xhr 的浏览器中进行本地测试,请删除 this.status === 200 。

importNode() 函数似乎在 IE 中不起作用(例如 9)。我收到一个模糊的“接口不支持”错误。

您也可以这样做:

var doc = this.responseXML;
var markup = (new XMLSerializer()).serializeToString(doc.getElementsByTagName("response")[0].getElementsByTagName("div")[0]);
div.innerHTML = markup;

只要标记对于空元素的结束标记而言是 HTML 友好的。

Here's a way to do it for Firefox, Opera, Chrome and Safari. Basically, you just do div.innerHTML = div.innerHTML to reinterpret its content as HTML, which will make that class attribute from the XML file be treated as an HTML class name.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title></title>
        <script>
            window.addEventListener("DOMContentLoaded", function() {
                var div = document.getElementsByTagName("div")[0];
                var req = new XMLHttpRequest();
                req.onreadystatechange = function() {
                    if (this.readyState === 4 && this.status === 200) {
                        var doc = this.responseXML;
                        div.appendChild(document.importNode(doc.getElementsByTagName("response")[0].getElementsByTagName("div")[0], true));
                        div.innerHTML = div.innerHTML;
                        alert(document.getElementsByClassName("colorSelector").length);
                    }
                };
                req.open("GET", "div.xml");
                req.send();
            }, false);
        </script>
    </head>
    <body>
        <div class="testA"></div>
    </body>
</html>

Remove the this.status === 200 if you're testing locally in browsers that support xhr locally.

The importNode() function doesn't seem to work in IE (9 for example). I get a vague "interface not supported" error.

You could also do it this way:

var doc = this.responseXML;
var markup = (new XMLSerializer()).serializeToString(doc.getElementsByTagName("response")[0].getElementsByTagName("div")[0]);
div.innerHTML = markup;

as long as the markup is HTML-friendly as far as end tags for empty elements are concerned.

短暂陪伴 2024-12-14 07:58:58
<!--<div class="colorSelector" id="0-0">
        <div class="gbSelector" id="1-0">
            <table style="none" id="2-0"></table>
        </div>
    </div>-->

上面的代码是灰色的有一个原因:它是一个注释。评论根本不会被浏览器解析,并且对页面没有任何影响。

您必须解析 HTML、读取注释并使用注释内容创建一个新的 DOM 对象。

<!--<div class="colorSelector" id="0-0">
        <div class="gbSelector" id="1-0">
            <table style="none" id="2-0"></table>
        </div>
    </div>-->

The above code is gray for a reason: it's a comment. Comments aren't parsed by the browser at all and have no influence on the page whatsoever.

You'll have to parse the HTML, read the comments, and make a new DOM object with the contents of the comment.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文