在网页网页开发中,经常会需要获取某个网页元素的子元素,然后对其进行事件绑定、或样式修改等行为。这些操作对于jquery来说很容易,但是对于原生js会稍微麻烦一些,这里将介绍四种方法获取元素的子元素(本文推荐第四种方法,如果时间有限,请直接把把滚轮滑到底↓↓↓↓↓)
一、childNodes
childNodes属性可以获取节点元素的子节点,并将获取到的子节点封装成一个对象:
<div class="test" id="test">
<p></p>
<p>3</p>
<p></p>
</div>
<script>
var a = document.getElementById("test");
var b = a.childNodes;
</script>
上面的代码就把childNodes获取到的对象保存在了b中,但这样写也会带来一个问题:
上面的div中有3子子元素,但是console.log(b)却发现输出的对象中有七个元素
因为根据dom的标准,标签之间的回车空格等特殊字符属于文本节点,上面的div中输入了4个回车,因此会多出四个text节点:
要解决这个问题有两个方法:
方法一:去掉所有的回车空格等特殊字符,但是会严重影响程序的可读性。
方法二:过滤掉不需要的空白字符:
思路是这样:通过for循环遍历对象中的所有元素,删除对象中我们不需要的元素
因此完整的代码就是这样:
var a = document.getElementById("test");
var b = a.childNodes;
for(i=;i<b.length;i++){
if(b[i].nodeName == "#text"){
a.removeChild(b[i]);
}
}
(网上有人判断这么写:if(b[i].nodeName == "#text" && !/\s/.test(b.nodeValue)),但我觉得&&后面那一半完全没有用。因为文本节点不管内容是什么,它的nodeValue属性的值都是null,它必然不等于/\s/,如果我的理解不对,麻烦评论告知以下)
想要操作子元素,只需要b加下标就可以了,比如想要修改第一个p标签的颜色:
b[].style.color='red';
二、child属性
child属性比childNodes方便得多,它不会返回文本节点。因此只需要一行代码就可以完成上面的操作
var a = document.getElementById("test").children;
修改第一个p标签的颜色
a[].style.color="red";
还有firstchild,lastchild这种见名知意的属性就不展开说了
三、获取后代节点
还是上面的例子,通过getElementById、getElementsByTagName、getElementBysClassName都可以获得后代元素节点。
下面的方法可以实现共和之前两种方法相同的功能:
var a = document.getElementById("test");
var b = a.getElementsByTagName('p');
还可以把方法中的p改为“*”,这样所有的子节点都能获取到,不管是什么类型的标签。
但是这种方法会获div的所有后代节点,只要符合条件,就会被获取到,即使它不是子节点:
<--下面的例子里,inner_test模块里的p标签也会被获取到-->
<div class="test" id="test">
<p></p>
<p></p>
<p></p>
<div class = "inner_test">
<p>我不是test的子节点</p>
</div>
</div>
除此之外,getElementsByTagName还有一个致命的缺点,就是它不能兼容ie6、7、8。
四、querySelector,强烈推荐!
querySelector的参数是选择器,任何选择器都可以作为它的参数:
<div class="first">
<span>张三</span>
</div>
<div id="second">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<script>
//通过类选择器获取节点
doucument.querySelector('.first');
//通过id选择器获取节点
doucument.querySelector('#second');
//通过伪类选择器获取节点
document.querySelector('.first>span');
//确认selectAll批量获取节点
document.querySelectorAll('#second>div');
</script>
可以使用伪类选择器这一特点,使得querySelect非常简单而且灵活,它不仅限于子节点,使用~就可以获取兄弟节点,使用空格就可以获取后代节点
在批量操作节点这方面,querySelectAll也甩出了getElementsByTagName、getElementBysClassName一百条街,
这种方法是目前我知道的最好的方法,简单易懂,而且还能兼容ie8及以上的版本。