JavaScript DOM、递归、遍历API、查找元素

810 阅读4分钟

1.DOM概念:Document Object Model

     提供了专门用于操作HTML文档的API
     
  • DHTML:

    动态的HTML,一切实现网页动态效果的技术的统称
          HTML+CSS+JS(DOM)
          
     面试/笔试题:HTML/XHTML/DHTML/XML:
      HTML:网页
      XHTML:更严格的网页
      DHTML:动态的网页
      XML:数据格式
     
    
  • DHTML模型:

    DOM:WSC标准
    BOM:Browser Object Model
      提供专门用于操作浏览器的API
      没有标准,但是大部分浏览器厂商已经统一的实现了,除了老IE,具有大量的兼容性问题。使用的较少(重点:定时器、event事件)
      
    
  • DOM:本来是可以操作一切结构化文档(HTML/XML)的:3部分

    1.核心DOM:万能!但是API比较繁琐:elem.setAttribute("属性名","属性值")
    2.HTML DOM:只能操作HTML文档,API非常简单:elem.属性名=值;
    3.XML DOM:XML基本已经淘汰很多年了
    

    建议:优先使用HTML DOM,实现不了,再用核心DOM补充

2.DOM树:

保存所有网页内容的树状结构:树根:document,不需要创建,由浏览器的JS解释器自动创建,一个页面只有一个树根
    DOM节点/对象/元素都有三大属性:
  1.xx.nodeType:获取xx的节点类型
       document9
       元素标签:1
       文本节点:3
       属性节点:2
       对于现在的开发者来说,没用
   2.属性节点nodeValue:获取属性节点的节点值
       依然没用,现在用getAttribute("")能直接获取属性的值
   3.xx.nodeName:获取属性节点的名称:
        何时使用:直接获取子元素的话,可能会找到多种标签,但是希望对不同标签执行不同的操作时使用
        特殊:获取出来的标签都是全大写

3.通过节点之间的关系获取元素:

1.父:elem.parentNode;
2.子:elem.children;--集合:只能找到儿子级
3,第一个儿子:elem.firstElementChild;
4.最后一个儿子:elem.lastElementChild;
5.前一个兄弟:elem.previousElementSibling;
6.后一个兄弟:elem.nextElementSibling

4.递归:函数中,再一次调用函数自己

作用:专门用于【遍历层级不明确的树状结构】
如何实现:21.创建函数,传入实参树根,形参接住,直接做第一层要做的操作
          function f1(root){
                 直接做第一层要做的操作
                 //判断自己有没有下一级,如果有再次调用此方法,但传入的实参已经变成了下一级
                 }
    2.调用函数 
      f1(实际的根元素)
     算法:深度优先,优先遍历当前节点的子节点
           子节点遍历完,才会跳到兄弟节点
     递归:优点:直观,易用
           缺点:效率较低,同时开启的函数很多,占用内存空间
      循环:优点:效率较高
            缺点:难度大

例题:

<ul id="ul">
    <li>电影</li>
    <li>动漫
        <ul>
            <li>剑风传奇</li>
            <li>海绵宝宝</li>
            <li>哆啦A梦</li>
        </ul>
    </li>
    <li>剧集</li>
</ul>

<script>
    //从树根开始就操作
    // function f1(root){
    //     root.style.border="1px solid #000"
    //    for(var i=0;i<root.children.length;i++){
    //            f1(root.children[i])
    //     }
    // }
    // f1(ul);

	//跳过了树根操作内部
    function f1(ch){
      for(var i=0;i<ch.length;i++){
          ch[i].style.border="1px solid #000"
          if(ch[i].children.length>0){
              f1(ch[i].children)
          }
      }
    }
    f1(ul.children)
</script>

5.遍历API:专门用于遍历【层级不明确的树状结构】

 2步:
 1.创建treewalker对象
     var tw=document.createTreeWalker(root,NodeFilter.SHOW_ALL/SHOW)
         
 2。反复调用nextNode方法:
     while((node=tw.nextNode())!=null){
              node;//当前节点做什么操作
              }
              深度优先算法
              注意:此方法会跳过起点

例题:

 <ul id="ul">
		<li>电影</li>
		<li>动漫
			<ul>
				<li>剑风传奇</li>
				<li>海绵宝宝</li>
				<li>哆啦A梦</li>
			</ul>
		</li>
		<li>剧集</li>
	</ul>
	<script type="text/javascript">
		var tw=document.createTreeWalker(ul,NodeFilter.SHOW_ELEMENT);
		
		while((node=tw.nextNode())!=null){
			node.style.border="1px solid #000";
		}
	</script>

6.纯循环遍历层级不明确的树状结构

例题:

 	<ul id="ul">
		<li>电影</li>
		<li>动漫
			<ul>
				<li>剑风传奇</li>
				<li>海绵宝宝</li>
				<li>哆啦A梦</li>
			</ul>
		</li>
		<li>剧集
			<ul>
				<li>剑风传奇</li>
				<li>海绵宝宝</li>
				<li>哆啦A梦</li>
			</ul>
		</li>
		
	</ul>
	<script type="text/javascript">
		function getChildes(root){
			var org=root;//org=ul
			while(true){
				root.style.border="1px solid #000";
				if(root.firstElementChild){
					root=root.firstElementChild
				}else if(root.nextElementSibling){
					root=root.nextElementSibling
				}else{//没有儿子,也没有下一个兄弟
					while(!root.parentNode.nextElementSibling&&root!=org.lastElementChild){
						root=root.parentNode;
					}
					root=root.parentNode.nextElementSibling;
					if(root==org.lastElementChild){
						root.style.border="1px solid #000";
						break;
					}
				}
			}
		}
		getChildes(ul);
	</script>
            

总结:以后不用遍历API(只能遍历页面元素),也不用纯循环(难度大),遇到层级不明确的时候,使用递归(不仅遍历元素,还能遍历数据)

7.查找元素:

 1.按照HTML的特点去查找元素:4var elem=document.getElementById("id名");
     找到了是单个元素,没找到一定是一个null
     var elem=document.getElementByTagName/ClassName/Name("标签/class名/name值")
     找到了是一个集合,没找到一定是一个空集合[]
 2.按照CSS选择器进行查找:21.单个元素,没找到一定是个null,如果有多个,也只会找到第一个
          var elem=document.querySelector("任意CSS选择器")
   2.多个元素:找到的是一个集合,没找到空集合
          var elem=document.querySelectorAll("任意CSS选择器")
       

面试题:getXXX和querySelectXXX的区别?

    1.返回结果不同:
         getXXX  -返回的是一个动态集合(每次DOM树修改,都会悄悄的再次查找)
         querySelectXXX  -返回的是一个静态集合(每次DOM树修改,不会再次查找,只管第一次找到的结果)
    2.动态集合,不支持forEach
      静态集合,支持forEach
    3.复杂查找时,尽量使用var elem=document.querySelectorAll("任意CSS选择器")