我正在尝试开发嵌入式小部件。用户将在其页面中包含一个anchor
标签和一个javascript,它将呈现内容。类似于嵌入式推文。
<a href="http://localhost:3000/user/13"
target="_blank"
class="my-widget"
data-widget-type="profile"
data-widget-identifier="id"
data-identifier-value="13"
>Sayantan Das</a>
</div>
<script src="//localhost/my-widget/js/widget.js" async ></script>
然后从widget.js
中,我将使用class="my-widget"
获得所有元素,并用iframe
替换。
widgets.js
!function(global, document) {
global.MyWidgets = global.MyWidgets || {};
for(let widgets = document.getElementsByClassName('my-widget'), i = 0; i < widgets.length; i++) {
console.log(widgets)
let element = widgets[i];
let span = document.createElement('span');
span.innerHTML = "Changed from widget " + i;
element.parentNode.appendChild(span);
element.parentNode.removeChild(element);
}
}(window, document);
问题是,当我删除元素时,循环还会运行较短的数字。例如,如果有两个元素的类为my-widget
,则在第一次运行循环后,将删除一个元素,并且循环仅运行一次。如何替换所有元素?
答案 0 :(得分:1)
这是因为getElementsByClassName
返回了实时 HTMLCollection
;当您从DOM中删除class="my-widget"
元素时,该元素也将从集合中删除。
要么向后浏览整个集合(因此您要从头开始删除,这不会影响到之前的集合),或者使用querySelectorAll(".my-widget")
来返回快照NodeList
,而不是实时HTMLCollection
。
后退:
for(let widgets = document.getElementsByClassName('my-widget'), i = widgets.length - 1; i >= 0; i--) {
改为使用qSA:
for(let widgets = document.querySelectorAll('.my-widget'), i = 0; i < widgets.length; i++) {
,或者如果您不需要i
(您似乎只是在使用它来获取元素并用于演示目的),则可以将for-of
与NodeList
s一起使用(在大多数平台上; this answer为其他平台提供了一个polyfill):
for (const element of document.querySelectorAll('.my-widget')) {
// ...and remove the `let element = ...` line
答案 1 :(得分:0)
使用document.querySelectorAll
达到小部件的长度