javascript高级程序设计 第10章 DOM 节点层次 Node

来源:互联网 发布:知字笔顺怎么写 编辑:程序博客网 时间:2024/04/29 20:02

节点层次 Node

1. NodeList对象反映在NodeList对象中。NodeList是有生命、有呼吸的对象

2. 接触到了 Array.prototype.slice.call(nodes, 0); 这方法 类似arguement.slice(0) 但效率高很多,所以推荐直接使用前者。 Array.prototype.slice.call(nodes, 0);可能call 会有疑问,因为arguement不是array,所以不能直接使用slice方法,需要用callappay“打破”这情况 

具体的可以看http://topic.csdn.net/u/20080725/09/162cb47f-be44-44bf-adcf-2a0ea7538454.html 

书中应用了:  

    function convertToArray() {

var array = null;

try{

//针对非ie

array = Array.prototype.slice.call(nodes, 0); 

}catch(ex){

array = new Array();

for(var i=0; len=nodes.length; i<len;i++){

array.push(nodes[i]);

}

}

return array;

    }   

3. nextSibling and previousSibling

与同胞节点相关,有着同一个parentNode都可以称为同胞节点

firstChildlastChild

someNode.firstChild = someNode.childNodes[0]

someNode.lastChild = someNode.childNodes[length-1]

如果只有一个子节点,则firstChild = lastChild

如果没有子节点,则firstChildlastChild 都为 null

hasChildNodes() 该方法在节点包含一或多个子节点的情况下返回true;比查询childNodes列表的length属性更简单的方法

4. 操作节点

appendChild() 用于向childNodes列表的末尾添加一个子节点

var returnedNode = someNode.appendChild(newNode);

alert(returnedNode == newNode); //true;

alert(someNode.lastChild == newNode); //true;

appendChild 的传入父节点的第一个子节点,那么该节点就会成为父节点的最后一个子节点。

    var returnedNode = someNode.appendChild(newNode);

    alert(returnedNode == newNode); //true;

    alert(someNode.lastChild == newNode); //true;

    var returnedNode = someNode.appendChild(someNode.fisrtChild);

    alert(returnedNode == someNode.firstChild); //false

    alert(returnedNode == someNode.lastChild); //true

insertBefore( node, index_node)要插入的节点和作为参照的节点

    插入后成为最后一个子节点

    returnedNode = someNode.insertBefore(newNode, null);

    alert(returnedNode == someNode.lastChild);

    插入后成为第一个子节点

    var returnedNode = someNode.insertBefore(newNode, someNode.firstNode);

    alert(returnedNode == newNode);//true

    alert(newNode == someNode.firstChild); //true

    插入到最后一个子节点前面

    returnedNode = someNode.insertBefore(newNode, someNode.lastChild);

    alert(newNode == someNode.childNodes[someNode.childNodes.length-2]);

replaceChild(node,index_node) 参数是要插入的node和要替换的node

    替换第一个子节点

    var returnedNode = someNode.replaceNode(newChild, someNode.firstNode);

    替换最后个子节点

    returnedNode = someNode.replaceNode(newChild, someNode.lastNode);

removeChild(index_node) 参数是要删除的node

            //移除第一个子节点

            var returnedNode = someNode.removeChild(newChild, someNode.firstNode);

            //移除最后个子节点

            returnedNode = someNode.removeChild(newChild, someNode.lastNode);

另外还有其他操作:

cloneChild(bool) 

        var deepList = myList.cloneNode(true);//深复制

var shallowList = myList.cloneNode(false);  //浅复制

cloneChild() 只复制特性、(在明确指定的情况下也复制)子节点

normalize() 处理文档树中的文本节点

Document类型

Document节点 nodeType(9) nodeName("#document") nodeValue(null) parentNode(null)

childNode(DocumentType{1},Element{1},ProcessingInstruction,Comment)

游览器内置了两个快速访问Document节点的子节点 

(1).documentElement元素 (2).childNodes列表

作为HTMLDocument的实例,document对象还有一个body属性,直接指向<body>元素

var html = document.documentElement;  //取得html

var body = document.body;

var doctype = document.doctype; 

素游览器对doctype分歧较大 

1.文档信息

第一个属性是 title,可以通过js操作修改title,但修改title属性的值并不修改<title>

        //取得文档标题

        var originalTitle = document.title;

        //设置文档标题

        document.title = "啦啦啦,我们祖国美好的河山"

        //取得完整的url

        var url = document.URL;

        //取得域名

        var domain = document.domain;

        //取得来源页面的url

        var referer = document.referrer;

其中domain是可以设置的,但是不能设置URL中不包含的域。由于跨域完全限制,来自不同子域的页面无法通过javascript通信,而通过将每个页面的document.domain设置为相同的值,这些页面就可以相互访问对方包含的javascript对象了。

Document.domain 设置成松散(loose)的后无法再设置回紧绷(tight)的,否则会出错

document.domain = "wrox.com";//松散的(成功)

document.domain = "p2p.wrox.com";  //紧绷的(出错)

2.查找元素

getElementById()getElementsByTagName()

1).getElementById() 

接受一个参数,要取得元素的ID,要求id特性严格匹配包括大小写。

如果页面多个元素的ID值相同,getElementById()只返回文档的第一次出现的元素。

另外 idname最好不要相同,不然ie7及以下版本会傻傻分不清

2).getElementByTagName()

取得元素的标签名,返回包含零或多个元素的NodeList。在HTML文档中,这个方法会返回一个HTMLCollection对象,作为一个“动态”集合,该对象与NodeList非常类似

        var images = document.getElementsByTagName("img");

alert(images.length);

alert(images[0].src); //输出第一个图像元素的src特性

alert(images.item(0).src); //输出第一个图像元素的src特性

HTMLCollection对象还有一个方法,namedItem();在提供按索引访问项的基础上,HTMLCollection还支持名称访问项。而且还能使用方括号语法来访问

var myImage = images.namedItem("myImage");

var myImage = images["myImage"];

还可以向getElementByTagName()中传入*。在javascriptcss中星号(*)通常表示“全部”

只有HTMLDocument类型才有的方法,是getElementByName()

返回带有给定name特性的所有元素

var radios = document.getElementsByName("color");

3).getElementByName()方法也会返回一个HTMLCollection对象,但是如果name特性相同的话,那么namedItem()只能返回第一项...

3.特殊集合

document.anchors document.links 前者包含文档中所有带name特性的<a>元素,后者是包含所有带href特性的<a>元素

document.forms 与 document.getElementsByTagName("form")类似

document.images与 document.getElementsByTagName("image")类似

4.DOM一致性检测

Document.implementation 存放了游览器实现了DOM哪些部分

hasFeature(检测的DOM功能的名称,版本号但实行者(游览器)会自行决定是否返回true

所以在进行使用DOM的某些特殊的功能之前,最好除了检测hasFeature()之外,还要能力检测。

5.文档写入

Write()writeln()open()close()

Writeln() 则会在字符串的末尾添加一个换行符(\n)

此外 write()writeln()能动态地包含外部资源

        document.write("<script type=\"text/javascript\"></scr" + "ipt>");

如果在文档加载结束后再调用document.write() 那么输出的内容将会重写整个页面

Open() close() 分别用来打开和关闭网页的输出流

Element类型

nodeType(1),nodeName(元素标签名),nodeValue(null),parentNode(Document 或 Element)

childNodes(Element,Text,Comment,ProcessingInstruction,CDATSectionEntityReferencd)

        var div = document.getElementById("myDiv");

        alert(div.tagName);

        alert(div.tabName == div.nodeName);

html中,标签名始终以全部大写表示

        var element;

        if (element.tabName.toLowerCase() == "div") {

            //执行操作

        }

1.HTML元素

所有的HTML元素都是由HTMLElement类型表示,不是直接通过这个类型,也是通过它的子类型来表示,继承来自Element

Idtitlelang(元素内容的语言代码),dir(语言方向,ltrrtl),className

2.取得特性

1).getAttribute()

传递给getAttribute()特性名与实际特性名相同。因此要获得到class特性值,应该传入“class”而不是“className”,后者只有通过对象属性访问特性时才用。此外g还可以取得自定义特性。

       var value = div.getAttribute("my_special_attribute");

只有公认的特性才会以属性形式添加到dom对象中。

        //unndefined ie除外

        alert(div.my_special_attribute);

但有两类特殊的属性值,通过getAttribute()返回的值并不相同。第一类是stylegetAttribute()返回的是css文本,通过属性返回的是一个对象。第二个是类似onlcikc的事件处理程序,getAttribute()返回的相应代码字符串,通过属性返回的是一个javascript函数。因此用js操作DOM的时候推荐使用对象的属性,而只有使用自定义特性值的情况下才会使用getAttribute();

2).setAttribute()

接受两个参数,要设置的属性名和值,如果特性已经存在,会以指定的值替换现有的值;如果特性不存在,则创建该属性并设置相应的值。

通过setAttribute()方法既可以操作HTML特性也可以操作自定义特性。通过这个方法设置的特性名会被统一转换为小写形式...

通上文一样,还是推荐使用属性来设置值,只有当面临自定义特性的时候会使用serAttribute()

3).removeAttribute()

清楚特性的值,而且也会从元素中完全删除特性

            div.removeAttribute("class");

3.attributes属性

包含一个NamedNodeMap,与NodeList类似,是一个动态的集合。元素的每一个特性都由一个Attr节点表示,每个节点都保存在NamedNodeMap对象中。

NamedNodeMap包含以下方法:

getNamedItem(),removeNamedItem(name),setNamedItem(node),item(pos)

attributes属性包含一系列节点,每个节点的nodeName就是特性的名称,而节点的nodeValue就是特性的值

var id = element.attributes.getNamedItem("id").nodeValue;

var id = element.attributes["id"].nodeValue;

设置值

element.attributes["id"].nodeValue = "otherId";

removeNamedItem()方法在元素上调用removeAttribute()是相同的,两者唯一的区别是

removeNamedItem()返回表示被删除的特性的Attr

        var oldAttr = element.attributes.removeNamedItem("id");

一般来说更多的是使用getAttribute(),removeAttribute()setAttribute()等方法

但当遍历元素的特性时,attribute将会派上用场

        function outputAttributes(element) {

            var pairs = new Array();

            for (var i = 0; len = element.attributes.length; i++) {

                var attrName = element.attributes[i].nodeName;

                var attrValue = element.attributes[i].nodeValue;

                //针对ie

                if (element.attributes[i].specified) {

                    pairs.push(attrName + "=\"" + attrValue + "\"");

                }

            }

            return pairs.join(" ");

        }

4.创建元素

使用document.createElement()方法可以创建新元素。只接受一个参数,即要创建元素的标签名,这个标签名在HTML文档中不区分大小写。

        var div = document.createElement("div");

还可以操作元素的特性,为它添加更多的子节点。

        div.id = "myNewDiv";

        div.className = "box";

以上这些设置这些特性,并没有添加到文档树中,也就是说游览器中不会显示。只有使用了appendChild()insertBefore()replaceChild()方法。

        document.body.appendChild(div);

一旦将元素添加到文档树中,浏览器就会立即呈现该元素。

而在IE中,可以将完整的元素标签传入createElement(),如:

        var div = document.createElement("<div id=\"myDiv\" class=\"box\"></div >");

写可以有助于避开IE7及以上版本中动态创建元素的一些问题

1)不能设置动态创建的<iframe>元素的name特性

2)不能通过表单的reset()方法重设动态创建的<input>元素

3)动态创建的type特性值为“reset”的<button>元素重设不了表单

4)动态创建的一批name相同的单选按钮彼此毫无关系。Name值相同的一组单选按钮本来应该表示同一选项的不同值,但动态创建的一批这种单选按钮之间却没有这种关系。

以上这些问题都可以用过在createElement()中指定完整HTML标签来解决,但其他的浏览器不支持,需要注意

5.元素的子节点

元素可以有任意数目的子节点和后代节点,因为元素可以是其他元素的子节点。元素的

childNodes属性中包含了它所有的子节点。这些子节点有可能是元素、元素节点、注释或处理指令。由于浏览器的不同,所以在执行某项操作以前,通常都要先检查一下nodeType属性。

        for (var i = 0; len = element.childNodes.length; i++) {

            if (element.childNodes[i].nodeType == 1) {

                //执行操作

            }

        }

Text类型

nodeType3nodeName的值为“#text”, nodeValue的值为节点包含的的文本, parentNode是一个Element,不支持(没有)子节点。可以通过nodeValue属性或data属性访问Text节点中包含的文本,这两个属性中包含的值相同。对nodeValue的修改也会通过data反映出来,反之亦然。

        appendData(text);//文本

        deleteData(offset, count); //offset 指定的位置 count 数量

        insertData(offset, text);

        replaceData(offset.count, text);

        splitText(offset);

        substringData(offset, count)

    <!--没有内容,也就没有文本节点-->

    <div></div>

    <!--有空格,因而有一个文本节点-->

    <div> </div>

    <!--有内容,因而有一个文本节点-->

    <div></div>

还可以用别的方法访问文本节点 如

        var textNode = div.firstChild;

        div.firstChild.nodeValue = "some other message"

如果这个文本节点当前存在于文档树中,那么修改文本节点的结果就会立即得到反映。另外修改的文本字符串会经过html编码,小于号、大于号或引号会被转义。

1.创建文本节

document.createTextNode()创建文本节点

        var textNode = document.createTextNode("<strong>123</strong>");

一般的每个元素只有一个文本子节点,但是不排除多个子节点

        var textNode = document.createTextNode("<strong>123</strong>");

        var element = document.createElement("div");

        element.className = "message";

        var textNode = document.createTextNode("Hello world");

        element.appendChild(textNode);

        var anotherTextNode = document.createTextNode("Tippee");

        element.appendChild(anotherTextNode);

       document.body.appendChild(element);

2.规范化文本节点

DOM文档中存在相邻的同胞文本节点很容易导致混乱,因为分不清哪个文本节点表示哪个字符串。如果在一个包含两个或多个文本节点的父元素的上调用normalize()方法,则会将所有文本节点合并成一个节点,结果节点的nodeValue等于将合并前每个文本节点的nodeValue值拼接起来的值。

        alert(element.childNodes.length);  //2

        element.normalize();

        alert(element.childNodes.length);  //1

        alert(element.firstChild.nodeValue);  //"Hello world;Yippee"

3.分割文本节点

splitText() 这个方法会将一个文本的节点分成两个节点

            var newNode = element.firstChild.splitText(5); //节点的位置 length

            alert(element.firstChild.nodeValue); //"hello"

            alert(newNode.nodeValue); //" world"

            alert(element.childNodes.length); //2

Comment类型

nodeType 8nodeName "#comment"nodeValue 注释内容,parentNode DocumentElement,不支持(没有)子节点

Comment类型与Text类型继承自相同的基类,因此它拥有除了splitText()之外的所有字符串操作的方法。与Text类型相似,也可以通过nodeValuedata属性取得注释的内容。

    <div id="myDiv"><!--a comment--></div>

    <script type="text/javascript">

        var div = document.getElementById("myDiv");

        var comment = div.firstChild;

        alert(comment.data);

    </script>

另外使用document.createComment()并为其传递注释文本也可以创建注释节点。

CDATASection类型

CDATASection类型只针对基于XML的文档,表示的是CDATA区域。与comment类似,CDATASection类型继承自Text类型,因此拥有除splitText()之外的所有字符串操作方法。

CDATASection nodeType 4, nodeName #cdata-section”,nodeValue CDATA区域的内容,parentNode DocumentElement),不支持(没有)子节点CDATA区域只会出现在XML文档中,因此多数浏览器都会把CDATA区域错误地解析为Comment或者Element

DocumentType类型

只有FirefoxSafariOpera支持它,DocumentType包含着与文档的doctype有关的所有信息。nodeType 10nodeName doctypenodeValue null, parentNode Document,不支持(没有)子节点。DocumentType 3个属性:nameentitiesnotationsname表示文档类型。

document.doctype.name; //"HTML"

ie不支持,所以ie返回的一直是null

DocumentFragment类型

nodeType 11nodeName "#document-fragment"nodeValue"null"parentNode"null"

子节点可以是ElementProcessingInstructionCommentTextCDATASection

EntityReference

不能将文档片段直接添加到文档中,但可以将它作为一个“仓库”来使用,即可以在里面保存将来可能会添加到文档中的节点。

        var fragment = document.createDocumentFragment();

文档片段继承了Node的所有方法。如果将文档中的节点添加到文档片段中,就会从文档树中移除该节点。在将文档片段作为参数传递给appendChild()insertBefore(),实际上只会将文档片段的所有节点添加到相应位置上,文档片段本身永远不会成为文档树的一部分。

        var fragment = document.createDocumentFragment();

        var ul = document.getElementById("myList");

        var li = null;

        for (var i = 0; i < 3; i++) {

            li = document.createElement("li");

            li.appendChild(document.createTextNode("item" + (i + 1)));

            frameElement.appendChild(li);

        }

        ul.appendChild(fragment);

Attr类型

元素的特性在DOM中以Attr类型来表示。

nodeType 11nodeName 特性的名称,nodeValue 特性的值,parentNode null,在HTML中不支持(没有子节点),在xml中子节点可以是TextEntityReference

Attr对象有3个属性:namevaluespecified

        var element = document.getElementById("myDiv");

        var attr = document.createAttribute("align");

        attr.value = "left";

        element.setAttributeNode(attr);

        alert(element.attributes["align"].value); //"left"

        alert(element.getAttributeNode("align").value); //"left"

        alert(element.getAttribute("align"));  //"left"

不建议直接访问特性节点。使用getAttribute()setAttribute()、和removeAttribute()方法远比直接访问特性节点要方便。

原创粉丝点击