我知道如何用jQuery做到这一点,但我想学习它与香草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:一个节点被插入到某个地方它不属于。"什么好主意吗?
flem的答案不正确。尽管在任何版本的HTML中,<li>
元素作为<span>
元素的子元素都是无效的,但对于DOM来说,这应该不是一个问题,事实上也不是。
有两个关键的信息你需要理解。首先,getElementsByTagName
返回的节点列表是附加到DOM文档的活动列表。如果JS循环改变了DOM文档,那么列表就会被更新。
第二种情况是,您只创建了一次包装器元素,但每次在循环中都与replaceChild一起使用它。
所以第一次循环一切正常。第二次循环时,克隆元素被添加到包装器中,包装器现在位于DOM文档中,因此成为y
节点列表中的第二个元素。
所以y[i]
不再是源<li>
,而是克隆元素,因此y[i].parentNode
是包装元素。
这意味着在replacecchild行中,您的代码试图使包装器元素成为其自身的子元素。这是不可能的,因此HIERARCHY_REQUEST_ERR
您正在构建一个无效的DOM。<li>
必须属于<ul>
或<ol>
,但您试图将其放在<span>
中。因此错误:"一个节点被插入到它不属于的地方"。