0

我知道如何用 jQuery 做到这一点,但我想用 vanilla javascript 来学习它,我觉得它会更快。这是 jsFiddle 的链接,其中包含我正在尝试做的精简版本。http://jsfiddle.net/yramagicman/MyM2B/以下是有问题的脚本。

<script>
var id = 'ul';
var tag = 'li';
var wrapTag = 'span';
var wrapper = document.createElement(wrapTag);
var z = document.getElementById(id);
var y = z.getElementsByTagName(tag);
var count = y.length;
for (var i = 0; i < count; i++) {
    y[i].setAttribute("class", "red"); //so I can see the result
    wrapper.appendChild(y[i].cloneNode(true));
    y[i].parentNode.replaceChild(wrapper, y[i]);
    wrapper.setAttribute('class', 'hi'); //so I can see the result
}</script>
<!-- and the html-->
<ul id="ul" class="ul">
    <li class="li">1</li>
    <li class="li">2</li>
    <li class="li">3</li>
    <li class="li">4</li>
    <li class="li">5</li>
    <li class="li">6</li>
    <li class="li">7</li>
    <li class="li">8</li>
</ul>

我可以将整个 Ul 包装在一个 div 或 span 或其他任何东西中,但是当我尝试包装每个列表项时,我收到错误“HIERARCHY_REQUEST_ERR:DOM 异常 3:节点被插入到它不属于的地方。” 有任何想法吗?

4

2 回答 2

2

弗莱姆的回答不正确。尽管元素在任何版本的 HTML 中<li>都不能作为元素的子<span>元素,但它不应该成为 DOM 的问题,事实上并非如此。

您需要了解两个关键信息。首先是返回的节点列表getElementsByTagName是一个附加到 DOM 文档的活动列表。如果 JS 循环更改了 DOM 文档,那么列表就会更新。

第二个是您创建了一次包装器元素,但每次在循环中都将其与 replaceChild 一起使用。

所以第一次在循环中一切正常。第二次循环时,克隆的元素被添加到包装器中,它现在位于 DOM 文档中,因此成为y节点列表中的第二个元素。

所以y[i]不再是源<li>,而是克隆元素,因此y[i].parentNode是包装元素。

这意味着在 replaceChild 行上,您的代码正试图使包装元素成为其自身的子元素。这是不可能的,因此 HIERARCHY_REQUEST_ERR

于 2013-01-20T01:45:52.837 回答
0

您正在构建一个无效的 DOM。<li>必须属于<ul><ol>但您正试图将其放在<span>. 因此出现错误:“一个节点被插入到它不属于的地方”

于 2013-01-19T18:32:17.407 回答