我可以使用getElementsByTagName选择多个标签吗?
A
是,但是您将不得不多次使用getElementsByTagName。
getElementsByTagName返回一个HTMLCollection对象,所以理想的结果将是为提供的所有标记名返回元素的HTMLCollection对象的方法。
HTMLCollection's的注意事项>
无法修改。
的所有匹配元素。
最简单的方法是使用返回querySelectorAll的nodeList
函数。
var nodeList = document.querySelectorAll(selector);
一种替代方法是对每个标签使用getElementsByTagName
方法,将返回的HTMLCollection对象转换为数组,以便可以将它们合并在一起。
像这样。var HTMLCollectionArray = [];
var names = selector.split(",");
for (var i = 0, n = names.length; i < n; i++){
HTMLCollectionArray = HTMLCollectionArray.concat(Array.prototype.slice.call(document.getElementsByTagName(names[i])));
}
nodeList也可以使用相同的方法转换为数组。
HTMLCollectionArray = Array.prototype.slice.call(nodeList);
我们现在可以将所有元素作为数组返回,也可以尝试返回HTMLCollection。
如果要返回HTMLCollection,则必须将其移动或将元素复制到单个parentNode以便访问parentNode.children
。 我发现使用document.createDocumentFragment
效果最佳。
var createDocumentFragment = document.createDocumentFragment();
for (var i = 0; i < HTMLCollectionArray.length; i++) {
createDocumentFragment.appendChild(HTMLCollectionArray[i]);
};
HTMLCollection = createDocumentFragment.children;
return HTMLCollection;
尽管这将返回正确的类型(HTMLCollection),但在调用该方法时,它不会返回元素的实际状态。 DOM已被修改以实现此目的。这不是一个好主意。
所以这使我们可以制作伪造的HTMLCollectionwindow.MyNodeList = function(elements) {
for ( var i = 0; i < elements.length; i += 1 ) {
this[i] = elements[i];
}
Object.defineProperty( this, 'length', {
get: function () {
return elements.length;
}
});
Object.freeze( this );
};
window.MyNodeList.prototype.item function ( i ) {
return this[i] != null ? this[i] : null;
}
window.MyHTMLCollection = function(elements) {
MyNodeList.call(this, elements);
}
MyHTMLCollection.prototype = Object.create(MyNodeList.prototype);
MyHTMLCollection.prototype.constructor = MyHTMLCollection;
window.MyHTMLCollection.prototype.namedItem = function ( name ) {
for ( var i = 0; i < this.length; i += 1 ) {
if ( this[i].id === name || this[i].name === name ) {
return this[i];
}
}
return null;
}
用法
var HTMLCollection = new MyHTMLCollection(elementsArray);
现在将所有内容拼凑在一起。
我还实现了'getElementsByClassNames'方法和'getElementsByTagNames',它们都使用相同的核心方法getElementsBySelector
。Element.prototype.getElementsByTagNames = Document.prototype.getElementsByTagNames = function(selector){
return this.getElementsBySelector(selector, 'getElementsByTagName');
}
Element.prototype.getElementsByClassNames = Document.prototype.getElementsByClassNames = function(selector){
return this.getElementsBySelector(selector, 'getElementsByClassName');
}
[我们只希望Document和Element接口继承我们的新方法,因为它们调用并非在所有Node接口中都存在的原型方法。例如getElementsByClassName
,querySelectorAll
等
如果要缩小代码,则可以使用Node.prototype代替声明Element.prototype.
和Document.prototype.
Node.prototype.getElementsByTagNames = function(selector){
return this.getElementsBySelector(selector, 'getElementsByTagName');
}
Node.prototype.getElementsByClassNames = function(selector){
return this.getElementsBySelector(selector, 'getElementsByClassName');
}
只需确保您不尝试在不是Document或Element的任何节点上使用它。
Element.prototype.getElementsBySelector = Document.prototype.getElementsBySelector = function (selector, HTMLCollectionType) {
var HTMLCollectionArray = [];
if(typeof this.querySelectorAll !== 'undefined'){
var nodeList = this.querySelectorAll(selector);
HTMLCollectionArray = Array.prototype.slice.call(nodeList);
} else {
if(typeof HTMLCollectionType !=='undefined' && typeof this[HTMLCollectionType] !== 'undefined'){
var names = selector.split(",");
for (var i = 0, n = names.length; i < n; i++){
HTMLCollectionArray = HTMLCollectionArray.concat(Array.prototype.slice.call(this[HTMLCollectionType](names[i])));
}
}
}
return new MyHTMLCollection(HTMLCollectionArray);
/*
var createDocumentFragment = document.createDocumentFragment();
for (var i = 0; i < HTMLCollectionArray.length; i++) {
createDocumentFragment.appendChild(HTMLCollectionArray[i]);
};
HTMLCollection = createDocumentFragment.children;
return HTMLCollection;
*/
}
用法
var element = document.getElementById('id');
element.getElementsbyClassNames('class1,class2,class2');
element.getElementsbyTagNames('li,div,p');
document.getElementsbyClassNames('class1,class2,class2');
document.getElementsbyTagNames('li,div,p');
同时选择两个标签?是的,我们可以同时创建一个循环。这是您的整个示例。但是一个循环(一个数组)同时具有P和LI:
function increaseFontSize() {
Array.from(document.getElementsByTagName('p'))
.concat(Array.from(document.getElementsByTagName('li'))).forEach(el => {
if(el.style.fontSize) {
var s = parseInt(el.style.fontSize.replace("px",""));
} else {
var s = 14;
}
if(s != max) {
s += 1;
}
el.style.fontSize = s+"px"
});
}
说明:Array.from()这是从集合中制作真实数组的官方方法。某些浏览器可能在HTMLCollection上支持forEach,但未在规范中。即使这样,他们也可能不支持concat()方法。使用from()将创建集合的浅表副本。这是HTMLCollection的优势,因为可以在迭代过程中修改项目并且对Array内部元素的修改仍将是对原始对象的修改。
现在我们有两个标准数组,可以使用concat()将它们连接起来,并且forEach可以迭代连接的结果。