通过DOM中的前置元素实现无限循环
不寻找使用框架XXX答案
这个问题不是为了通过框架找到实际的解决方案。回答使用框架XXX,或者这在框架XXX中很容易,或者为什么不使用这个框架XXX??不能回答问题。
我有一个在页面加载后运行的函数:performShim
。此函数迭代DOM中作为span
标记的所有元素,检查它们是否具有className
的shim
,如果有,则调用shim
向其传递匹配元素的引用。
我的目标是在span
前面添加另一个span
,该iframe
包含传递给shim
的元素。
使用我到目前为止编写的代码,我能够很好地将追加到元素的父级。然而,如果我注释掉append
行,而不是尝试前缀行,浏览器可能会挂起一个无限循环。
我不太清楚为什么会是这样。
function shim( element ) {
var iframe = document.createElement('iframe');
iframe.setAttribute( 'frameborder', '0' );
iframe.setAttribute( 'scrolling', 'no' );
iframe.setAttribute( 'align', 'bottom' );
iframe.setAttribute( 'marginheight', '0' );
iframe.setAttribute( 'marginwidth', '0' );
iframe.setAttribute( 'src', "javascript:'';" );
var span = document.createElement('span');
span.appendChild(iframe);
//element.parentNode.insertBefore(span,element); //causes infinite loop?
element.parentNode.appendChild(span); //this line works OK
var els = element.style;
var originalVisibility = els.visibility;
var originalPosition = els.position;
var originalDisplay = els.display;
els.visibility = 'hidden';
els.position = 'absolute';
els.display = 'inline';
var width = element.offsetWidth;
var height = element.offsetHeight;
els.display = originalDisplay;
els.position = originalPosition;
els.visibility = originalVisibility;
iframe.style.width = (width-6) + 'px';
iframe.style.height = (height-6) + 'px';
}
function performShim() {
var children = document.getElementsByTagName("span");
for( var i = 0; i < children.length; i++ ) {
if( children[i].className == "shim" ) {
shim(children[i]);
}
}
}
解决方案
ANodeList
(如document.getElementsByTagName
返回的那个)通常是一个实时列表--您对DOM所做的更改也会显示在其中。因此,每次在当前元素之前添加span
时,您就是将列表扩展了一个元素,并将当前元素移动了一个元素,而下一次迭代会将您带回到刚刚完成的节点。
您有几个简单的解决方法来解决这个问题...
添加节点时撞到计数器。(丑陋的,如果您最终添加的是某项内容而不是span
,您将最终跳过节点,原因将不明显。)将列表复制到数组并迭代该数组。您可以使用
children = [].slice.call(children, 0);
(更常见)或
children = Array.apply(window, children);
。使用
/li>document.querySelectorAll
,这将返回一个非活动的NodeList。(即使它是实时的,在这种情况下,您也可以选择'span.shim'
,插入的跨度无论如何都不会显示在其中。)向后迭代(从
children.length - 1
到0)。
相关文章