简体   繁体   English

是否可以将 append 元素添加到 JavaScript 节点列表?

[英]Is it possible to append an element to a JavaScript nodeList?

I'm generating content dynamically, so I'm often ending up with documentFragments which I'm querying using querySelectorAll or querySelector returning a nodeList of elements inside my documentFragment.我正在动态生成内容,所以我经常以使用querySelectorAll或 querySelector 查询的documentFragments结束,或者querySelector返回我的nodeList中的元素节点列表。

From time to time I would like to add an item to a list, but I can't find anything online on whether this is even possible.有时我想将一个项目添加到列表中,但我在网上找不到任何关于这是否可能的信息。

I tried it like this:我试过这样:

 document.querySelectorAll(".translate").item(length+1) = document.createElement("div");

and this:和这个:

 document.querySelectorAll(".translate").shift(document.createElement("div"));

But both don't work (as expected)但两者都不起作用(如预期的那样)

Question:问题:
Is it possible to manually add elements to a NodeList?是否可以手动将元素添加到 NodeList? I guess, not but asking nevertheless.我想,不是,而是问。

Thanks for some insights?感谢您的一些见解?

EDIT :编辑
So more info: I'm generating a block of dynamic content, which I want to append to my page.所以更多信息:我正在生成一个动态内容块,我想将其 append 到我的页面。 By default the block is in English.默认情况下,该块是英文的。 Since the user is viewing the page in Chinese, I'm running a translator on the dynamic fragment, BEFORE appending it to the DOM.由于用户正在查看中文页面,因此我在动态片段上运行翻译器,然后将其附加到 DOM。 On my page, I also have an element, say a title, which should change depending on the dynamic content being added.在我的页面上,我还有一个元素,比如标题,它应该根据添加的动态内容而改变。 My idea was to do this in one step = try to add an element to my nodeList .我的想法是一步完成 = 尝试向我的nodeList添加一个元素。 But from writing it now... I guess not possible:-)但是从现在开始写......我想不可能:-)

EDIT: As @Sniffer mentioned, NodeLists are read-only (both the length property and the items).编辑:正如@Sniffer 提到的,NodeLists 是只读的(长度属性和项目)。 You can manipulate everything else about them, like shown below, but it's probably better to convert them to arrays instead if you want to manipulate them.您可以操作关于它们的所有其他内容,如下所示,但如果您想操作它们,最好将它们转换为数组。

var list = document.querySelectorAll('div');
var spans = document.querySelectorAll('span');

push(list, spans);
forEach(list, console.log); // all divs and spans on the page

function push(list, items) {  
  Array.prototype.push.apply(list, items);
  list.length_ = list.length;
  list.length_ += items.length;
}

function forEach(list, callback) {
  for (var i=0; i<list.length_; i++) {
    callback(list[i]);
  }
}

It would probably be a better idea to turn the NodeList to an array instead ( list = Array.prototype.slice(list) ).将 NodeList 改为数组可能是一个更好的主意( list = Array.prototype.slice(list) )。

var list = Array.prototype.slice.call(document.querySelectorAll('div'));
var spans = Array.prototype.slice.call(document.querySelectorAll('span'));

list.push.apply(list, spans);
console.log(list); // array with all divs and spans on page

I have another suggestion.我还有一个建议。 You can select multiple nodes by query separator ( , ), This code will save all h2 and h3 tags saved in nodes variable:您可以通过查询分隔符 ( , ) 选择多个节点,此代码将保存所有保存在节点变量中的 h2 和 h3 标签:

var nodes = document.querySelectorAll('h2, h3');

Unlike previously described element selection methods, the NodeList returned by querySelectorAll()is not live: it holds the elements that match the selector at the time the method was invoked, but it does not update as the document changes.与之前描述的元素选择方法不同,querySelectorAll() 返回的 NodeList 不是实时的:它保存在调用方法时与选择器匹配的元素,但不会随着文档的变化而更新。 [1] [1]

The NodeList in this case is not alive, so if you add/remove anything to/from it, then it won't have any effect on the document structure.在这种情况下, NodeList不是活动的,因此如果您向它添加/从中删除任何内容,那么它不会对文档结构产生任何影响。

A NodeList is a read-only array-like object. NodeList 是一个只读的类似数组的对象。 [1] [1]

[1]: JavaScript: The Definitive Guid, David Flanagan [1]: JavaScript:权威指南,大卫·弗拉纳根

To not get into technicalities with array methods it can sometimes be more readable to make a list of node names and loop over the list.为了不涉及数组方法的技术问题,有时可以制作一个节点名称列表并遍历该列表更具可读性。

In this example I assign the same event handler to all buttons in two different radio button groups (where each button in the group has the same name):在这个例子中,我为两个不同单选按钮组中的所有按钮分配了相同的事件处理程序(组中的每个按钮都具有相同的名称):

<div>
    <input type="radio" name="acmode" value="1" checked="checked">Phase<br>
    <input type="radio" name="acmode" value="2">Ssr<br>
    <input type="radio" name="acmode" value="3">Relay<br>
</div>
<div>
    <input type="radio" name="powermode" value="0"  checked="checked">Manual<br>
    <input type="radio" name="powermode" value="1">Automatic<br>
</div> 

Sample event handler:示例事件处理程序:

var evtRbtnHandler =
    function rbtnHandler() {
        document.getElementById("response11").innerHTML = this.name + ": " + this.value;
    }

And assigning:并分配:

var buttongroup = ["acmode", "powermode"];
buttongroup.forEach(function (name) {
    document.getElementsByName(name).forEach(function (elem) {
        elem.onclick = evtRbtnHandler;
    });
});

In any case once you get your hands on each single item it can be pushed() to an array using human readable code.在任何情况下,一旦您掌握了每个项目,就可以使用人类可读的代码将其 push() 到一个数组中。

Use ES6 Set():使用 ES6 Set():

var elems = new Set([
    ...document.querySelectorAll(query1),
    ...document.querySelectorAll(query2)
]);

NodeLists are readonly, so we cannot mutate it directly. NodeLists 是只读的,所以我们不能直接改变它。 But here is how you can add new item to a NodeList.但这里是如何将新项目添加到 NodeList。

let list = document.querySelector("#app").childNodes; // node list
list = list[0]; // selecting the first element in node list
list.parentNode.appendChild(/* new elements */); // adding to parent of current node

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM