DOM--初级

DOM(Document Object Model)即文档对象模型,针对HTML和XML文档的API(应用程序接口)。DOM描绘了一个层次化的节点树,运行开发人员添加、移除和修改页面的某一部分。DOM脱胎于Netscape及微软公司创始的DHTML(动态HTML),但现在它已经成为表现和操作页面标记的真正跨平台、语言中立的方式。

一.DOM介绍

DOM中的三个字母,D(文档)可以理解为整个Web加载的网页文档;O(对象)可以理解为类似window对象之类的东西,可以调用属性和方法,这里我们说的是document对象;M(模型)可以理解为网页文档的树型结构。
DOM有三个等级,分别是DOM1、DOM2、DOM3,并且DOM1在1998年10月成为W3C标准。DOM1所支持的浏览器包括IE6+、Firefox、Safari、Chrome和Opera1.7+。
PS:IE中的所有DOM对象都是以COM对象的形式实现的,这意味着IE中的DOM可能会和其他浏览器有一定的差异。
HTML中
    <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>Document</title>
        </head>
        <body>
            <p>hello world</p>
        </body>
    </html>
    文档元素(文档的最外层的元素):<html>

    文档中,只能有一个文本元素。HTML的文档元素永远为<html>元素,而XML没有预定义的外层结构,所有任何元素都能为文档元素。

1.查找元素

元素节点方法
方法                                  说明
getElementById()                获取特定ID元素的节点
getElementsByTagName()          获取相同元素的节点列表
getElementsByName()             获取相同名称的节点列表
getAttribute()                  获取特定元素节点属性的值
setAttribute()                  设置特定元素节点属性的值
removeAttribute()               移除特定元素节点属性 
例如:
    <div id="box">
        this is div
    </div>

1.1 getElementById()方法

    getElementById()方法,接受一个参数:获取元素的ID。如果找到相应的元素则返回该元素的HTMLDivElement对象,如果不存在,则返回null。
    var box = document.getElementById('box');   
    console.log(box);       
    //<div id="box">
    //  this is div
    //</div>获取id为box的元素节点
PS:如果DOM没有加载完成,默认情况返回null,这无关是否存在id="box"的标签,而是执行顺序问题。
解决方法:
    1.把script调用标签移到html末尾即可;
    2.使用onload事件来处理JS,等待html加载完毕再加载onload事件里的JS。
    window.onload = function () {               //预加载html后执行
        document.getElementById('box');
    };
    PS:id表示一个元素节点的唯一性,不能同时给两个或以上的元素节点创建同一个命名的id。某些低版本的浏览器会无法识别getElementById()方法,比如IE5.0-,这时需要做一些判断,可以结合上章的浏览器检测来操作。
    if (document.getElementById) {              //判断是否支持getElementById
        alert('当前浏览器支持getElementById');
    }
    当我们通过getElementById()获取到特定元素节点时,这个节点对象就被我们获取到了,而通过这个节点对象,我们可以访问它的一系列属性。
元素节点属性
    属性                      说明
    tagName             获取元素节点的标签名
    innerHTML           获取元素节点里的内容,非W3C DOM规范
    document.getElementById('box').tagName;     //DIV
    document.getElementById('box').innerHTML;   //  this is div(注意前后是有空格的,因为原div中就是有空格的)
HTML属性的属性
    属性                  说明
    id              元素节点的id名称
    title           元素节点的title属性值
    style           CSS内联样式属性值
    className       CSS元素的类
    document.getElementById('box').id;              //获取id
    document.getElementById('box').id = 'person';   //设置id

    document.getElementById('box').title;           //获取title
    document.getElementById('box').title = '标题' //设置title

    document.getElementById('box').style;           //获取CSSStyleDeclaration对象
    document.getElementById('box').style.color;     //获取style对象中color的值
    document.getElementById('box').style.color = 'red'; //设置style对象中color的值

    document.getElementById('box').className;           //获取class
    document.getElementById('box').className = 'box';   //设置class   

    alert(document.getElementById('box').bbb);      //获取自定义属性的值,非IE不支持

1.2 getElementsByTagName()方法

        <p>this is p1</p>
        <p>this is p2</p>
        <p>this is p3</p>
    getElementsByTagName()方法将返回一个对象数组HTMLCollection(NodeList),这个数组保存着所有相同元素名的节点列表。
    document.getElementsByTagName('p');         //HTMLCollection:[p, p, p]获取所有元素

    document.getElementsByTagName('p');         //获取所有p元素,返回数组
    document.getElementsByTagName('p')[0];      //<p>this is p1</p>,获取第一个p元素
    document.getElementsByTagName('p').item(0)  //<p>this is p1</p>,获取第一个p元素
    document.getElementsByTagName('p').length;  //3,获取所有p元素的数目

    PS:不管是getElementById还是getElementsByTagName,在传递参数的时候,并不是所有浏览器都必须区分大小写,为了防止不必要的错误和麻烦,我们必须坚持养成区分大小写的习惯。

1.3 getElementsByName()方法

    getElementsByName()方法可以获取相同名称(name)的元素,返回一个对象数组HTMLCollection(NodeList)。
    document.getElementsByName('add')           //获取input元素
    document.getElementsByName('add')[0].value  //获取input元素的value值
    document.getElementsByName('add')[0].checked    //获取input元素的checked值

    PS:对于并不是HTML合法的属性,那么在JS获取的兼容性上也会存在差异,IE浏览器支持本身合法的name属性,而不合法的就会出现不兼容的问题。

1.4 getAttribute()方法

    getAttribute()方法将获取元素中某个属性的值。它和直接使用.属性获取属性值的方法有一定区别。
    document.getElementById('box').getAttribute('id');//获取元素的id值
    document.getElementById('box').id;          //获取元素的id值

    document.getElementById('box').getAttribute('mydiv');//获取元素的自定义属性值
    document.getElementById('box').mydiv        //获取元素的自定义属性值,非IE不支持

    document.getElementById('box').getAttribute('class');//获取元素的class值,IE不支持
    document.getElementById('box').getAttribute('className');//非IE不支持

    PS:HTML通用属性style和onclick,IE7更低的版本style返回一个对象,onclick返回一个函数式。虽然IE8已经修复这个bug,但为了更好的兼容,开发人员只有尽可能避免使用getAttribute()访问HTML属性了,或者碰到特殊的属性获取做特殊的兼容处理。

1.5 setAttribute()方法

    setAttribute()方法将设置元素中某个属性和值。它需要接受两个参数:属性名和值。如果属性本身已存在,那么就会被覆盖。
    document.getElementById('box').setAttribute('align','center');//设置属性和值
    document.getElementById('box').setAttribute('bbb','ccc');//设置自定义的属性和值

    PS:在IE7及更低的版本中,使用setAttribute()方法设置classstyle属性是没有效果的,虽然IE8解决了这个bug,但还是不建议使用。

1.6 removeAttribute()方法

    removeAttribute()可以移除HTML属性。
    document.getElementById('box').removeAttribute('style');//移除属性

    PS:IE6及更低版本不支持removeAttribute()方法。

2.Node类型

元素节点                Node.ELEMENT_NODE(1)
属性节点                Node.ATTRIBUTE_NODE(2)
文本节点                Node.TEXT_NODE(3)
CDATA节点                Node.CDATA_SECTION_NODE(4)
实体引用名称节点          Node.ENTRY_REFERENCE_NODE(5)
实体名称节点             Node.ENTITY_NODE(6)
处理指令节点             Node.PROCESSING_INSTRUCTION_NODE(7)
注释节点                 Node.COMMENT_NODE(8)
文档节点                 Node.DOCUMENT_NODE(9)
文档类型节点             Node.DOCUMENT_TYPE_NODE(10)
文档片段节点             Node.DOCUMENT_FRAGMENT_NODE(11)
DTD声明节点               Node.NOTATION_NODE(12)
可以利用nodeType属性来得出此节点类型多对应的数值。
a.nodeType==1表示a为一个元素。
例如:
    var box = document.getElementById("box");
    if(box.nodeType == 1){
        alert("this is a element")
    }

2.1 nodeName和nodeValue

nodeName:对于元素节点nodeName为元素名;
nodeValue:对于元素节点nodeValue永远为null
例如:
var box = document.getElementById("box");
if(box.nodeType == 1){
    console.log(box.nodeName)//DIV
    console.log(box.nodeValue)//null
}

2.2 节点关系

2.2.1childNode

<div id="box"><p>asdasdasdasd</p>
    <a href="###">321asd132as1d3a2s1d</a>
</div>
<script type="text/javascript">
    var box = document.getElementById("box");
    console.log(box.childNodes);
    //[p, text, a, text]
    // p和a元素之间有text是因为他们之间用enter进行了换行

    // childNodes属性中包含有NodeList属性(类数组但是不是数组)。NodeList中包含着所有的子元素,可以
    console.log(box.childNodes[0])//<p>asdasdasdasd</p>
    console.log(box.childNodes.item(0))
    //item()是一种方法
    console.log(box.childNodes.length)
</script>

2.2.2.将NodeList转化为数组

<script type="text/javascript">
    var box = document.getElementById("box");
    // box.childNodes.NodeList属性和arguments属性很像都可以用Array.prototype.slice方法将其转换为数组
    var a = Array.prototype.slice.call(box.childNodes,0);
    console.log(a)//[p, text, a, text]
    // 但是以上的代码在IE8以及之前是不能运行的。
    // 兼容版:
    function converToArray(nodes){
        var array = null;
        try{
            array = Array.prototype.slice.call(box.childNodes,0);//针对非IE
        }catch(ex){
            array = new Array();
            for(var i = 0;i<nodes.length;i++){
                array.push(nodes[i])
            }
        }
        return array;
    }
    // converToArray方式首先用最简单的放法,如果报错的话再用push
</script>

2.2.3.层次节点属性

    节点的层次结构可以划分为:父节点与子节点、兄弟节点这两种。当我们获取其中一个元素节点的时候,就可以使用层次节点属性来获取它相关层次的节点。
        属性                      说明
        childNodes          获取当前元素节点的所有子节点
        firstChild          获取当前元素节点的第一个子节点
        lastChild           获取当前元素节点的最后一个子节点
        ownerDocument       获取该节点的文档根节点,相当与document
        parentNode          获取当前节点的父节点
        previousSibling     获取当前节点的前一个同级节点
        nextSibling         获取当前节点的后一个同级节点
        attributes          获取当前元素节点的所有属性节点集合
        <div id="box"><p>asdasdasdasd</p>
            <a href="###" id="aa">321asd132as1d3a2s1d</a>
        </div>
        <script type="text/javascript"> 
        var  a = document.getElementById("aa");
2.2.3.1.parentNode
        // 指向该元素的父元素
        console.log(a.parentNode);
        // 指向的是div,会打印出整个div,包括它包裹的元素
        // <div id="box"><p>asdasdasdasd</p>
        // <a href="###" id="aa">321asd132as1d3a2s1d</a>
        // </div>
2.2.3.2.previousSibling
    //前一个兄弟节点,第一个元素的该属性为null
    console.log(a.previousSibling)
    //#text
2.2.3.3.nextSibling
    //后一个兄弟节点,最后一个元素的改属性为null
    console.log(a.nextSibling)
    //#text
2.2.3.4.firstChild,lastChild
    // firstChild:父元素的第一个子元素
    // lastChild:最后一个子元素
    var box = document.getElementById("box");
    console.log(box.firstChild);
    //<p>asdasdasdasd</p>
    console.log(box.lastChild)
    //#text
</script>


在看一个div是否为空时,可以用2.层次节点属性hasChildNodes(),这个属性在包含有1个或者多额子元素时返回true,

2.3.操作节点

节点操作方法
    方法                          说明
    write()                 这个方法可以把任意字符串插入到文档中
    createElement()         创建一个元素节点
    appendChild()           将新节点追加到子节点列表的末尾
    createTextNode()        创建一个文件节点
    insertBefore()          将新节点插入在前面
    repalceChild()          将新节点替换旧节点
    cloneNode()             复制节点
    removeChild()           移除节点

2.3.1.write()方法

    write()方法可以把任意字符串插入到文档中去。
    document.write('<p>这是一个段落!</p>')'   ;   //输出任意字符串

2.3.2.createElement()方法

    createElement()方法可以创建一个元素节点。
    document.createElement('p');                    //创建一个元素节点

2.3.3.appendChild

         向一个元素的尾部添加新的元素
            <div id="box"><p>asdasdasdasd</p>
                <a href="###" id="aa">321asd132as1d3a2s1d</a>
            </div>
            <p id="pp">hcd</p>
                <script type="text/javascript">     
                var box = document.getElementById("box");
                var p = document.getElementById("pp");   
                var a = box.appendChild(p)
                console.log(a)
                //<p id="pp">hcd</p>,appendChild()返回的是新增节点
                console.log(box)
                //box外面的p元素不见了,而是增加到了box中,
            </script>

2.3.4.createTextNode()方法

    createTextNode()方法创建一个文本节点。
    var text = document.createTextNode('段落');       //创建一个文本节点
    p.appendChild(text);                        //将文本节点添加到子节点末尾
    我们平时用的时候可以createElement创建新的元素,createTextNode创建文本节点,appendChild将文本节点插入到元素节点中,appendChild再将元素插入到我们想要的地方。

2.3.5.insertBefore

    参数1:新增的元素
    参数2:插入到哪个元素前面
    <div id="box"><p>asdasdasdasd</p>
        <a href="###" id="aa">321asd132as1d3a2s1d</a>
    </div>
    <p id="pp">hcd</p>
    <script type="text/javascript">     
        var box = document.getElementById("box");
        var p = document.getElementById("pp");
        var a = document.getElementById("aa");
        var b = box.insertBefore(p,a)
        console.log(b)
        //返回新增节点
        console.log(box)
        //div外的p将会移到a元素前面
    </script>

2.3.6.replaceChild替换子元素

    参数1:新增的元素
    参数2:要被提换的元素
        利用2的例子
        var b = box.replaceChild(p,a)

2.3.7.removeChild移除元素

    box.removeChild(a)

2.3.8.cloneNode复制

    1.深度复制
    var b = box.cloneNode(true);
    console.log(b)
    //和box元素一样,子元素也会被复制;

    2.浅复制
    var b = box.cloneNode(true);
    console.log(b)
    //只会复制box元素即div元素,子元素不会被复制

    注意:不会复制js属性和方法;但是ie有bug,会复制属性和方法

二.Document元素:

文档,并且是widnow的一个属性
特点:
    nodeType:9;
    nodeName:#document;
    nodeVale:null;
    parentNode:null
1.document.documentElement
    将<html>内的打印出来
2.document.title
    console.log(document.title)
    //打印文档的标题
    document.title = "new title";
    //设置文档的标题
3.
    console.log(document.URL)
    //获取完整的URL
    console.log(document.domain)
    //获取域名
    console.log(document.referrer)
    //来源页面的URL
    其中只有domain是可以设置的;但是设置的时候有要求:
    不能将这个属性设置为URL中没有的包含的域。
    如www.xp.com
    那么只能设置为xp.xom
    利用domain设置跨域也是很方便的
    如www.xp.com和p2p.xp.com
    可以将这两个页面的domain都设置为
    xp.xom;但是注意设置过一遍后,就不能再设置了,哪怕是设置回去也不行。
4.特殊集合
    document.anchors:文档中所有带有name属性的a标签
    document.forms:文档中所有的form元素
    document.images:文章中所有的img元素

三.Element元素用来表现HTML或者XML元素

nodeType:1;
nodeName:元素的名字;
nodeValue:null;
parentNode:Document或Element
要访问元素的标签名时,可以使用nodeName属性,也可以使用tagName属性。(但是注意返回的是大写)
例如:
    <div id="box"><p>asdasdasdasd</p>
    <a href="###" id="aa">321asd132as1d3a2s1d</a>
    </div>
    <p id="pp">hcd</p>
    <script type="text/javascript">     
        var box = document.getElementById("box");
        console.log(box.tagName)//DIV
        console.log(box.nodeName)//DIV
    </script>
    因为返回的是大写,所以再写一些判断的时候可以采用下面的方式:
    if(element.tagName.toLowerCase() == "div"){

    }

1.HTML元素

    可以拥有以下属性:
        id:元素的唯一标示;
        className:元素指定的类;
        title:有关元素的附加说明;一般通过工具条表示
        lang:语言标示
        dir:语言的方向

2.取的特性

        getAttribute()获取属性
        setAttribute()设置属性
        removeAttribute()移除属性
    例如:
        <div id="box" class="className" title="this is box" leng="en" dir="ltr" data-hcd="hcd" style="background:red;width: 200px;height: 200px;"></div>
        <script type="text/javascript">
            var box = document.getElementById("box");
            console.log(box.getAttribute("id"))          //"box"
            console.log(box.getAttribute("class"))       //"className"
            console.log(box.getAttribute("data-hcd"))    //"hcd"
            console.log(box.getAttribute("asdasd"))      //"null"
            console.log(box.getAttribute("style"))       //"background:red;width: 200px;height: 200px;"
            console.log(box.id)//"box"
            console.log(box.style)//一个cssstyle对象
        </script>
    上面的代码用来获取元素的属性,包括自定义属性,如果没有该属性就返回null。
    对于行内样式style,利用getAttribute返回的是css样式文本,利用属性来访问返回的却是一个对象。
    同样对于onclick,利用getAttribute返回的是onclick内的代码字符串,利用属性来访问返回的却是一个函数。
    由于这些差异,所以一般不会用getAttribute访问属性,而是使用对象属性(如:box.id),只用自定义属性采用getAttribute

3.设置属性

    通过box.setAttribute("id","newId");
    也可以通过box.id = "newId"来进行设置。
    但是通过以上的两种方法是不能够新增属性的。
    采用setAttribute方法会在IE7之前存在异常(name和style不能够设置),所以一般通过box.id = 的方法设置。

    removeAttribute()
    不仅会移除属性值,连属性也会一起移除

4.attributes

    元素有attributes属性,attributes属性中有NamedNodeMap,与NodeList类似,元素的每一个属性都作为一个attr节点存在NamedNodeMap中;
    例如:
        <div id="box" class="className" title="this is box" leng="en" dir="ltr" data-hcd="hcd" style="background:red;width: 200px;height: 200px;"></div>
        <script type="text/javascript">     
            var box = document.getElementById("box");
            console.log(box.attributes)//NamedNodeMap0:id 1:class  2:title  3: leng  4:dir  5:data-hcd  6:style  length:7  __proto__: NamedNodeMap
        </script>
    我们可以通过遍历将元素所有的所有属性以name:vale的方式打印出来。但是IE7会有问题,就是会返回所有的可能属性,不仅是自己设置的,是所有的。而自己设置的属性都会自动有specified属性,只要该属性为true就是用户自己设置的。
    function outputAttributes(element){
        var pairs = new Array(),
            attrName,
            attrValue,
            i;
        for(i = 0,i < element.attributes.length;i++){
            attrName = element.attributes[i].nodeName;
            attrValue = 
            element.attributes[i].nodeValue;
            if(element.attributes[i].specified){
                pairs.push(attrName + "=\""+attrValue+"|"")
            }
        }
        return pairs.join("");
    }

5.创建元素

    document.createElement()
    var div = document.createElement("<div id="newBox">this is div</div>")

6.获取子节点

    <ul id="ulbox">
        <li>a</li>
        <li>b</li>
        <li>c</li>
    </ul>
    <script type="text/javascript">     
        var ul = document.getElementById("ulbox");
        // 1.通过下面的方法获取ul的子元素,由于有enter键导致的分行,所以会有text元素
        for(var i = 0;i < ul.childNodes.length;i++){
            console.log(ul.childNodes[i])
        }
        // #text
        // <li>​a​</li>​
        // #text
        // <li>​b​</li>​
        // #text
        // <li>​c​</li>​
        // #text

        // 2.只获取ul下的li,nodeType==1表示为元素
        for(var i = 0;i < ul.childNodes.length;i++){
            if(ul.childNodes[i].nodeType==1){
                console.log(ul.childNodes[i])
            }
        }
        // <li>a</li>
        // <li>b</li>
        // <li>c</li>

        // 3.可以通过下面的方法获取到ul下li的集合
        var items = ul.getElementsByTagName("li")
        console.log(items)
    </script>

四.Text类型

表示的是纯文本内容,不含有HTML代码。
nodeType:3;
nodeName:#text;
nodeBValue:节点包含的而所有文本;
可以使用的方法:
    1.appendDate(text):将text添加到节点的尾部
    2.deleteDate(offset,count):从offset位置开始删除count个字符。
    3.insertDate(offset,text):从offset位置前插入text4.replaceDate(offset,count,text):用text替换offset开始到offset+count位置的字符(前闭后开)。
    5.splitText(offset):从offset指定的位置将当前文本节点分成两个文本节点。
    6.substringDate(offset,count):提取从offsetoffset+count处的字符。
<div></div>             //不含有文本节点
<div> </div>            //含有文本节点空格
<div>阿萨德 爱谁谁的</div>//含有文本节点“阿萨德 爱谁谁的”

可以设置文本节点,但是会进行HTML转义。
如:
    var box = document.getElementById("box");
    var text = box.childNodes[0];
    text.nodeValue = "<strong>asd</strong>"
    //输出结果为加粗版额asd

1.创建文本节点

document.createTextNode();
例如:
    <div id="box"></div>
    <script type="text/javascript">     
        var box = document.getElementById("box");
        var text = document.createTextNode("pppp");
        box.appendChild(text);
        var textb = document.createTextNode("ooooo");
        box.appendChild(textb);
        console.log(box.childNodes.length);
        //2
        box.normalize();
        console.log(box.childNodes.length);
        //1
    </script> 
创建2个text节点插入到div中,这时div的childNodes为2个,使用normalize()方法可以将这两个text节点合并

猜你喜欢

转载自blog.csdn.net/haochangdi123/article/details/77507331
DOM