DOM总结1:DOM基础

0. DOM简介


任何一种技术都是有它存在的意义,DOM正是为了方便操作HTML文档而诞生的技术。在没有DOM的时代,为了操作HTML元素曾发展出了DHTML(动态HTML),后来由于微软和Netscape的浏览器大战而销声匿迹。DOM脱胎于DHTML,并于1998年DOM 1级成为了W3C的推荐标准。现在利用JavaScript操作DOM已经成为基础前端技术,被各大浏览器完善支持。


DOM(Document Object Model,文档对象模型),是一种针对HTML和XML文档编程API。DOM将整个HTML或XML文档映射为一个层次化的节点树,用以节点的增删改查操作,以达到改变页面的目的。每个HTML或XML元素都可以看成一个节点,每个节点都有对应的数据和层次结构,使用JavaScript等脚本语言可以对节点的进行操作。

例如如下HTML文档:

<html>
    <head>
        <title>learnDOM</title>
    </head>
    <body>
        <p>hello</p>
        <h1>world</h1>
    </body>
</html>

可将此HTML文档表示为节点的层次结构:


其实html上册还有一个根节点:文档节点。html节点称为文档元素,任何一个HTML文档只有一个文档元素,因此html节点能表示整个文档。整个DOM树是一种典型的树状数据结构,例如body节点拥有两个子节点p和h1,文本节点"learnDOM"父节点为title。


1. 节点类型


DOM 1级定义了一个Node接口,该接口由DOM中所有节点类型来实现。相应的,在JavaScript中由Node类型实现了这个接口,JavaScript的其他所有节点类型都继承自Node类型,因此所有节点类型共享基本属性和方法。

每个节点都有一个nodeType属性来表明节点类型。Node类型定义了12个类型,由数值常量1~12来表示。常用节点类型有:

节点类型 数值常量 字符常量
Element(元素节点) 1 ELEMENT_NODE
Attr(属性节点) 2 ATTRIBUTE_NODE
Text(文本节点) 3 TEXT_NODE
Comment(注释节点) 8 COMMENT_NODE
Document(文档节点) 9 DOCUMENT_NODE
DocumentType(文档类型节点) 10 DOCUMENT_TYPE_NODE
DocumentFragment(文档片段节点) 11 DOCUMENT_FRAGMENT_NODE
除IE外各大浏览器都支持使用字符常量。下面简要列举各节点类型的含义:
1)Element(元素节点),是组成节点树的重要部分,通常拥有子元素、文本节点等子节点,也是唯一能拥有属性的节点类型,例如:
<html>, <head>, <meta>, <div>等

都是元素节点。


2)Attr(属性节点),是元素节点的一部分,不能单独作为节点出现在节点树中。例如:

<div id="addr"></div>

中id就是元素节点div的属性节点。


3)Text(文本节点),只包含文本内容的节点,在XML中也称为字符数据,可为空字符。节点树中,元素的文本内容和属性的文本内容都是由文本节点来表示的。例如:

<title>learnDOM</title>

中"learnDOM"就是文本节点。


4)Comment(注释节点),表示文档中注释的内容。


5)Document(文档节点),是文档的根节点。在HTML文档的节点树中处于html节点之上的节点为文档节点。


6)DocumentType(文档类型节点),每个文档都有一个类型属性,值或为空,或为DocumentType对象。在HTML中:

<!DOCTYPE html>

就是文档类型节点。


7)DocumentFragment(文档片段节点),是文档的片段,并不属于文档节点树。例如:

var frag = document.createDocumentFragment();

frag就为一个文档片段,可对其操作后写入文档树,文档片段就起了类似临时变量的作用。


接下来举一个判断节点类型的例子:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>learnDOM</title>
    </head>
    <body>
        <div id="addr">元素节点</div>
        <script>
            var divNode = document.getElementById("addr");
            if (divNode.nodeType === Node.ELEMENT_NODE) {
                console.log("A element node");
            }
        </script>
    </body>
</html>
将div节点的id"addr"传入getElementById()方法,得到一个节点元素divNode。判断divNode的类型可通过上述if语句。注意IE中只支持与数值常量,ELEMENT_NODE这种字符常量是无法识别的。

上例中通过节点元素的nodeType属性判断节点类型,除此之外常用属性还有nodeNamenodeValue。例如:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>learnDOM</title>
    </head>
    <body>
        <!-- learnNodeType -->
        <div id="addr">元素节点</div>
        <script>
            //元素节点
            var divNode = document.getElementById("addr");
            console.log(divNode.nodeName);   //div
            console.log(divNode.nodeValue);  //null

            //属性节点
            var attrNode = divNode.attributes[0];
            console.log(attrNode.nodeName);  //id
            console.log(attrNode.nodeValue); //addr

            //文本节点
            var textNode = divNode.childNodes[0];
            console.log(textNode.nodeName); //#text
            console.log(textNode.nodeValue);//元素节点

            //注释节点
            var commentNode = document.body.childNodes[1];//注释前空白为[0]
            console.log(commentNode.nodeName);//#comment
            console.log(commentNode.nodeValue);//learnNodeType

            //文档类型节点
            console.log(document.doctype.nodeName); //html
            console.log(document.doctype.nodeValue);//null
            
            //文档片段节点
            var frag = document.createDocumentFragment();//创建文档片段
            console.log(frag.nodeName);  //#document-fragment
            console.log(frag.nodeValue); //null
        </script>
    </body>
</html>

2.  DOM方法和属性


HTML文档被浏览器解析为一棵DOM树,要想操作HTML文档就要通过JavaScript来操作DOM节点。对DOM的操作可以总结为“增删改查”,即:增加DOM节点,删除DOM节点,更新DOM节点和查询遍历DOM节点。

DOM是一种对象,有其相应的方法和属性。通过DOM方法可以执行DOM操作,如增改节点元素;通过属性可以获取或设置节点。

通过各种DOM方法我们可以对HTML节点元素进行增删改查操作。常用方法有:
  • getElementById(),返回指定ID的元素
  • getElementsByTagName(),返回指定标签名称的所有元素节点集合
  • getElementsByClassName(),返回指定类名的所有元素节点集合
  • appendChild(),添加新节点到指定节点
  • removeChild(),删除子节点
  • replaceChild(),替换子节点
  • insertBefore(),在指定节点前插入新节点
  • createAttribute(),创建属性节点
  • createElement(),创建元素节点
  • createTextNode(),创建文本节点
  • getAttribute(),返回指定属性值
  • setAttribute(),修改指定属性值

常用的属性有:
  • innerHTML,节点文本值
  • parentNode,节点的父节点
  • childNodes,节点的子节点
  • attributes,节点的属性节点

下面在通过实例说明DOM方法和属性的常见用法:

2.1 DOM获取

若要操作DOM节点首先要获取到DOM节点。常见方法如document.getElementById()document.getElementsByTagName(),以及CSS选择器document.getElementsByClassName()。getElementById()与后两者区别在于:ID可以定位到HTML中唯的DOM节点,后两种方法会得到一组DOM节点。我们可以通过先定位父节点后向下选择的方法精确定位DOM。例如:
    <h1 id="country">countries</h1>
    <div id="div_list">
        <p class="AS">CN</p>
        <p class="NA">US</p>
        <p class="EU">UK</p>
        <p class="EU">FR</p>
        <p class="AS">JP</p>
        <p class="AS">KR</p>
    </div>

    <script>
        //获取ID为"country"的节点
        var countries = document.getElementById("country");

        //先定位ID为"div_list"的节点,后获取其内部所有p节点
        var ps = document.getElementById("div_list").getElementsByTagName("p");

        //先定位ID为"div_list"的节点,后获取其内部所有class为EU的节点
        var eus = document.getElementById("div_list").getElementsByClassName("EU");

        //获取div_list所有子节点,第一个子节点,最后一个子节点
        var divTest = document.getElementById("div_list");
        var divTestChilds = divTest.childNodes;
        var firstChild = divTest.firstChild;
        var lastChild = divTest.lastChild;
    </script>
或者用querySelector()querySelectorAll(),注意IE8+版本才有支持。具体用法见https://developer.mozilla.org/zh-CN/docs/Web/API/Document/

2.2 DOM修改

得到某个DOM节点后可对其进行修改。
1)修改innerHTML属性,innerHTML 属性设置或返回表格行的开始和结束标签之间的 HTML。可对节点文本进行修改:
        //获取节点
        var h = document.getElementById("country");
        
        //设置文本
        h.innerHTML = "hello";

        //设置HTML
        h.innerHTML = "hello <span style=\"color:red\">red</span> ";

2)修改innerTexttextContent属性。这两种属性可以对字符串进行HTML编码,防止恶意修改。用法与innerHTML类似。

3)修改CSS。DOM节点对象的style属性对应CSS格式设置,例如:
        var divTest = document.getElementById("div_list");

        divTest.style.color = "#00ff00";
        divTest.style.fontSize = "10px";

2.3 DOM删除

要删除一个节点首先要获取它本身及其父节点,通过调用父节点的removeChild()方法进行删除:
        //获取待删除节点
        var self = document.getElementById("div_list");
        
        //获取父节点
        var parent = self.parentNode;

        //删除
        var removed = parent.removeChild(self);

        console.log(removed === self); //true
若使用父节点的children属性进行遍历删除,注意children属性是只读的,并且随着操作会实时更新:
    <div id="div_list">
        <p class="AS">CN</p>
        <p class="NA">US</p>
        <p class="EU">UK</p>
        <p class="EU">FR</p>
        <p class="AS">JP</p>
        <p class="AS">KR</p>
    </div>

    <script>
        var parent = document.getElementById("div_list");

        parent.removeChild(parent.children[0]);
        parent.removeChild(parent.children[5]);//error,节点只剩了五个,children[5]不存在
    </script>


2.4 DOM插入

1)直接修改innerHTML。
当DOM节点为空时,直接修改其innerHTML属性即可“插入”节点。例如:
    <div id="blank"></div>
    
    <script>
        var d = document.getElementById("blank");
        d.innerHTML = "hello";
    </script>
但是节点非空时会将原内容覆盖。

2)appendChild()方法,将新节点插入到父节点最后。例如:
    <p id="kr">KR</p>
    <div id="div_list">
        <p class="AS">CN</p>
        <p class="NA">US</p>
        <p class="EU">UK</p>
        <p class="EU">FR</p>
        <p class="AS">JP</p>
    </div>
    <script>
        var list = document.getElementById("div_list");
        var kr = document.getElementById("kr");
        list.appendChild(kr);
    </script>
<p id="kr">KR</p>被插入到list最后,并且原位置的kr会被删除,相当于完成了节点的移动。

我们也能从零创建一个新节点并插入父节点中:
        var list = document.getElementById("div_list");
        var newNode = document.createElement("p");
        newNode.id = "kr";
        newNode.innerHTML = "KR";
        list.appendChild(newNode);

3)insertBefore()方法,能够灵活确定插入位置。该方法调用形式为:
parentElement.insertBefore(newElement, referenceElement);
能将子节点newElement插入到referenceElement之前。例如:
    <p id="kr">KR</p>
    <div id="div_list">
        <p class="AS">CN</p>
        <p class="NA">US</p>
        <p class="EU">UK</p>
        <p class="EU">FR</p>
        <p class="AS">JP</p>
    </div>
    <script>
        var list = document.getElementById("div_list");
        var ref = list.children[2];
        var node = document.getElementById("kr");
        list.insertBefore(node, ref);
    </script>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章