这个getElementsByClassName函数接受两个参数。第一个node表示DOM树中的搜索起点,第二个classname就是要搜索的类名了。如果传入节点上已经存在了适当的getElementsByClassName函数,那么这个新函数就直接返回相应的节点列表。如果getElementsByClassName函数不存在,这个新函数就会循环遍历所有标签,查找带有相应类名的元素。
这个方法的缺点是不适用于多个类名。
如果使用这个函数来模拟前面取得购物列表的操作,就可以这样写:
复制代码 代码如下:
var shopping=document.getElementById("purchase");
var sales = shopping.getElementsByClassName(shopping,"test");
console.log(sales);
因此,要解决文章开头的那道题目,所用代码如下:
复制代码 代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Shopping List</title>
</head>
<body>
<h1>What to buy</h1>
<p title="a gentle reminder">Don't forget to buy this stuff.</p>
<ul>
<li>A thin of beans</li>
<li>Cheese</li>
<li>Milk</li>
</ul>
<script>
function getElementsByClassName(node,classname){
if(node.getElementsByClassName){
return node.getElementsByClassName(classname);
}else{
var results = [];
var elems = node.getElementsByTagName("*");
for(var i=0;i<elems.length;i++){
if(elems[i].className.indexOf(classname)!=-1){
results[results.length]=elems[i];
}
}
return results;
}
}
var body = document.getElementsByTagName("body")[0];
var sales= getElementsByClassName(body,"sales");
console.log(sales);
</script>
</body>
</html>
Solution2 Robert Nyman方案
搜索匹配的DOM元素的方法还有很多,但真正高效的却不多,Jeremy Keuth大叔的方法有一个缺点就是不能用于多个类名,2008年,Robert Nyman在文章 The Ultimate GetElementsByClassName, Anno 2008中提供了自己的解决方案。在2005年,Robert大叔就已经给出了自己的getElementsByClassName的函数,在2008年的时候,修改了部分代码,添加了许多新的功能:
1.如果当前浏览器支持getElementsByClassName函数,则调用该原生函数;
2.如果当前浏览器支持则使用XPath;//小飞鱼:一种浏览器内置的定位XML文档的强大方式,不过浏览器支持方面不统一
3.支持多个类名的搜索,不计先后顺序;
4.返回真正的节点数组,而不是原生的一个nodelist。//小飞鱼:原生的getElementsByClassName方法返回的是一个NodeList对象,它很像数组,有length和数字索引属性,但并不是数组,不能用pop,push等数组特有的方法,Robert提供的代码中,将NodeList对象转成了数组。可以将NodeList对象转换成数组的方法:
复制代码 代码如下:
myList = Array.prototype.slice.call (myNodeList)
这是Robert大叔的方法,有些地方还不太明白,待我研究一下再来更新好了。
复制代码 代码如下: