使用js提取列表文本,练习操作dom节点
在html中写下一个无序列表,如下。
<ul id="menu">
<li>first</li>
<li><a href="">second1</a><a href="">second2</a><a href="">second3</a></li>
<li>third</li>
<li><b>fourth</b></li>
<li>fifth</li>
</ul>
以该列表作为一个dom树中的父节点,分析该节点的子节点,有5个li元素节点,需要注意的是,还有6个空白文本,即6个文本节点,如下图,红色框中的空白也为一个子节点,这种节点在该列表中共有6个。
图1
现在明确一下需求:把列表中的除去空白文本的文本(即first、second1、second2、second3、third、fourth、fifth)全部提取出来并放入一个数组。
1.要完成需求,首先要在script中编写js将ul列表获取
<script>
var ul_1 = document.querySelector("#menu");
//document.querySelector();方法是获取页面元素的选择器,按CSS样式查询,
//并返回第一个节点
</script>
此时,ul_1已经成为了一个父节点,若要提取其中的内容,是先想办法遍历所有子节点,在遍历的过程中判断哪些是需要的内容,再有选择性的把需要的内容压入设置好的数组,接下来先遍历所有子节点
2.遍历子节点
<script>
var ul_1 = document.querySelector("#menu");
//编写提取文本的方法_Filter(ele),传入的参数ele为一个父节点
function _Filter(ele) {
//遍历常用的for循环方法,把第一个子节点设为初始值并赋给i,每循环一次
//把i的下一个兄弟节点再赋给i,当下一个子节点为null,即没有下一个子节点
//时,终止循环
for (var i = ele.firstChild; i != null; i = i.nextSibling) {
}
}
}
</script>
3.设置数组,并选择文本节点压入数组
这一步是完成需求的难点 ,当第一次遍历子节点的时候,会遇见下面的问题
(1)空文本,即上面图1中用红色框框住的部分
(2)子节点为元素节点,并不能直接得到我们需要的里面的内容
针对第一个问题,解决起来相对容易,我们需要得到的是文本但不是空文本,所以在方法中加入如下判断便可把空文本筛选出去。
if(i.nodeType == Node.TEXT_NODE && i.nodeValue.trim()){}
再来解决第二个问题,子节点为元素节点。那我们可以把这个子节点看作是一个父节点,对该父节点的子节点再进行判断,如此判断直至找到其中的文本节点压入数组,或者其中是空文本节点筛选出去,要实现这一流程,使用递归函数会比较容易。代码如下:
<script>
var ul_1 = document.querySelector("#menu");
function _Filter(ele, data) {
//3.data参数是在下面第2步递归中传来的参数,把该数据传给数组
var result = data || [];
for (var i = ele.firstChild; i != null; i = i.nextSibling) {
//1.判断该子节点的类型是否为文本节点并且不是空文本的节点,如果
//该节点满足则直接压入数组,否则进行下一次判断
if(i.nodeType == Node.TEXT_NODE && i.nodeValue.trim()){
result.push(i.nodeValue);
//2.如果该子节点为元素节点,把该节点作为父节点再次传入我们写的
//_Filter方法,在这个传入的过程中我们还要注意的是把上面压入
//了我们所需内容的数组作为参数一并传过去。
}else if(i.nodeType == Node.ELEMENT_NODE){
_Filter(i,result);
}
}
//4.最后该方法返回遍历了每一个节点之后的数组,里面就是需要的内容
return result;
}
</script>
4.往该方法中传入父节点ul_1,在控制台中打印该方法的结果。
console.log(_Filter(ul_1);
图2
达到需求。
主要是递归的熟练运用、遍历方法、遍历逻辑、对dom节点的理解和节点方法的使用。