JavaScript笔记:DOM

来源:互联网 发布:管家婆sql下载 编辑:程序博客网 时间:2024/05/16 06:44

DOM对象是针对HTML和XML文档的一个API。DOM描绘了一个层次化的节点树,允许开发人员添加修改页面的一部分。

节点层次

DOM可以将HTML和XML文档描绘成一个多层节点组成的结构。节点分为不同的类型,每种类型分别表示文档中不同的信息或标记。每个节点都拥有各自的特点、数据和方法,与其它节点也可能存在某种关系。节点之间的关系构成了层次,所有页面的标记则表现为以特定节点为跟节点的树形结构。

1、Node类型

DOM1级定义了一个Node接口,该接口将由DOM中的所有节点类型实现。这个Node接口在JS中是作为Node类型实现的,除了IE浏览器之外,其他所有的浏览器都可以访问到这个类型。JS中所有的节点都继承自Node类型,因此所有的节点都共享着相同的基本属性和方法。

每个节点都有一个nodeType属性,用于表示节点的类型。节点类型由在Node类型中定义的下列12个数值常量表示,任何节点类型必居其一。

Node.ELEMENT_NODE(1) Node.ATTRIBUTE_NODE(2) Node.TEXT_NODE(3) Node.CDATA_SECTION_NODE(4) Node.ENTITY_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)    Node.NOTATION_NODE(12)。

通过比较上面这些常量,可以很容易的确定节点的类型。

if (someNode.nodeType == 1){  //在所有浏览器中有效     alert("Node is an element.");}

nodeName和nodeValue属性:

要了解节点的具体信息,可以使用nodeName和nodeValue属性。这两个属性完全取决于节点的类型。
检查节点类型:

if (document.getElementById("first").nodeType == 1){    value = document.getElementById("first").nodeName;     console.log(value);// DIV}

对于元素节点,nodeName保存的是元素的标签名,而nodeValue始终为null。
节点关系:

文档中的所有节点都存在这样或那样的关系。节点之间的关系就好像家族的家谱树。例如,在HTML中body是html元素的子元素,反过来说,html元素就是body元素的父元素。而head元素,则可以看成是body元素的同胞元素。每个节点都有一个childNodes属性,保存着一个NodeList对象,注意,NodeList对象并不是Array的实例,它是对DOM动态查询的结果。
使用方法:

var firstChild = someNode.childNodes[0];var secondChild = someNode.childNodes.item(1);var count = someNode.childNodes.length;

使用下列方法可以将NodeList转化为数组:

function convertToArray(nodes){        var array = null;        try {            array = Array.prototype.slice.call(nodes, 0); // IE中无效        } catch (ex) {            array = new Array();            for (var i=0, len=nodes.length; i < len; i++){                array.push(nodes[i]);            }        }        return array;}

每个节点都有一个parentNode的属性,指向文档中的父节点。包含在childNodes列表中的所有节点都有相同的父节点。另外,包含在childNodes列表中的所有节点都是同胞节点,可以使用节点属性previousSibling/nextSibling来访问节点的同胞节点。

if (someNode.nextSibling === null){    alert("Last node in the parent’s childNodes list.");} else if (someNode.previousSibling === null){    alert("First node in the parent’s childNodes list.");}

父节点的firstChild和lastChild分别指向其子节点的第一个和最后一个节点。

另外hasChildNodes()也是一个好用的方法,当节点包含子节点的时候,该方法返回true。

所有节点都有的最后一个属性是ownerDocument,该属性指向表示整个文档的文档节点。

操作节点:

因为关系指针都是只读的,所以DOM提供了一些操作节点的方法。其中,最常用的就是appendChild()方法,用于向childNodes列表的末尾添加一个节点。更新完成后,appendChild()方法返回新增的节点。

var returnedNode = someNode.appendChild(newNode); alert(returnedNode == newNode); //true alert(someNode.lastChild == newNode); //true

如果传入appendChild函数的节点已经是文档的一部分了,那结果就是将传入的节点移动到指定的位置。
如果需要把指定节点放在childNodes列表的某个特定位置上,而不是最后一个,那么就需要用到insertBefore方法。这个方法接受两个参数:要插入的节点和作为参照的节点。如果参照节点是null,那么insertBefore方法就和appendChild方法的作用一样了。

//插入后成为最后一个节点         returnedNode = someNode.insertBefore(newNode, null); alert(newNode == someNode.lastChild); //true//插入后成为第一个节点   var returnedNode = someNode.insertBefore(newNode, someNode.firstChild); alert(returnedNode == newNode); //truealert(newNode == someNode.firstChild); //true//插入到最后一个节点前面returnedNode = someNode.insertBefore(newNode, someNode.lastChild); alert(newNode == someNode.childNodes[someNode.childNodes.length-2]); //true

replaceChild函数:该函数接受两个参数,要插入的节点和要替换的节点。要替换的节点将由这个函数返回,同时要插入的节点将在DOM中取代被替换掉的节点。

//替换第一个子节点  var returnedNode = someNode.replaceChild(newNode, someNode.firstChild);//替换最后一个子节点returnedNode = someNode.replaceChild(newNode, someNode.lastChild);

如果只想移除而不是替换节点的话,可以使用函数removeChild(),该函数接受一个参数:要移除的节点。

其它方法:

有两个方法是所有类型的节点都具有的:cloneNode(),normalize()。
cloneNode方法接受一个布尔值的参数,表示是否进行深复制。如果进行深复制,那么该节点的所有包括子节点在内的信息都会被复制。如果只是浅复制,那么将只复制节点自身。
例如:

<ul>   <li>item 1</li>   <li>item 2</li>   <li>item 3</li></ul>

假设我们已经将ul节点保存在了myList中,那么下面这段代码就可以让我们看出两种复制的区别。

var deepList = myList.cloneNode(true);alert(deepList.childNodes.length); //3      var shallowList = myList.cloneNode(false);alert(shallowList.childNodes.length); //0

normalize方法用来处理文档树中的文本节点。当在某个节点上调用这个方法时,就会在该节点的后代中查找:1)空文本节点,找到后删除;2)相邻的文本节点,找到后合并成一个。

2、Document类型:

JavaScript通过Document类型表示文档。在浏览器中,document是HTMLDocument的一个实例,表示整个HTML页面。而且document是window对象的一个属性,因此,可以将其作为全局属性来访问。
document节点具有下列属性:
nodeType值为9;
nodeName的值为#document;
nodeValue、parentNode、ownerDocument的值为null。

Document类型可以表示HTML页面,不过最常见的应用还是作为document对象。通过这个对象,不仅可以获得与页面有关的信息,而且还可以操作页面的外观极其底层结构。

1、文档的子节点

document的documentElement属性:该属性始终指向HTML页面中的html元素。另外,document的childNodes也可以用来访问页面的元素。

var html = document.documentElement;//获得对<html>的引用alert(html === document.childNodes[0]);//truealert(html === document.firstChild);//true

作为HTMLDocument的实例,document还有一个属性body,直接指向页面的body标签:

var body = document.body; //取得对<body>的引用

所有的浏览器都支持document.documentElemen和document.body属性。

2、文档信息

作为HTMLDocument文档的一个实例,document还有一些普通Document对象所没有的属性,这些属性提供了document对象所表现的一些网页信息。
例如,title:

//获得文档标题var originalTitle = document.title;//设置文档标题document.title = "New page title";

接下来的三个属性都和网页请求有关:

//取得完整的URLvar url = document.URL;//取得域名var domain = document.domain;//取得来源页面的URLvar referrer = document.referrer;

这三个属性中,只有domain是可以设置的。但是,出于安全性问题的考虑,只能设置成URL中包含的域,否则就会出错:

//假设页面来自于p2p.wrox.com域document.domain = "wrox.com"; //成功document.domain = "nczonline.net"; //出错

浏览器对domain属性还有一个限制,即如果域名一开始是松散的,就不能将其设置为紧绷的。

//假设页面来自于p2p.wrox.com域document.domain = "wrox.com"; //松散的,成功document.domain = "p2p.wrox.com"; //紧绷的,失败

3、查找元素

最常见的DOM应用,应该就是获得特定的某个或某组元素的引用,然后再执行一些操作了。取得元素的操作可以使用document对象的几个方法完成:例如,getElementById()、getElementsByTagName()、getElementsByTagName()。

例子:

var images = document.getElementsByTagName("img");alert(images.length);alert(images[0].src);alert(images.item(0).src);

4、特殊集合

document.anchors:文档中所有带name属性的a标签
document.forms:文档中所有form标签
document.images:文档中所有img标签
document.links:文档中所有带href属性的a标签

5、DOM一致性检测

由于DOM包含了多个级别,也包含了多个部分,因此,检测浏览器实现了DOM的那些部分就十分重要了。
使用方法:

var hasXmlDom = document.implementation.hasFeature("XML", "1.0");

如果浏览器支持该版本,将返回true。

6、文档写入

将输出流写入网页的能力:

<html>    <head>        <title>document.write() Example</title>    </head>    <body>        <p>The current date and time is:            <script type="text/javascript">                document.write("<strong>" + (new Date()).toString() + "</strong>");             </script>        </p>    </body></html>

此外,还可以使用此方法动态的包含外部资源:

<html>    <head>        <title>document.write() Example 3</title>    </head>    <body>        <script type="text/javascript">            document.write("<script type=\"text/javascript\" src=\"file.js\">" +"<\/script>");        </script>    </body></html>

请注意双引号中的转意字符的写法。

Element类型

Element节点具有以下特点:
nodeType为1
nodeName/tagName为节点的标签名
nodeValue为null
parentNode可能是Document或Element

1、HTML元素

<div id="myDiv" class="bd" title="Body text" lang="en" dir="ltr"></div>// 获取属性var div = document.getElementById("myDiv");alert(div.id);//"myDiv"alert(div.className);//"bd"alert(div.title);//"Body text"alert(div.lang);//"en" 元素内容的语言代码alert(div.dir);//"ltd" 语言的方向// 修改属性div.id = "someOtherId";div.className = "ft";div.title = "Some other text";div.lang = "fr";div.dir ="rtl";

2、取得特性

getAttribute()、setAttribute()、removeAttribute()三个方法:

var div = document.getElementById("myDiv");alert(div.getAttribute("id"));//"myDiv"alert(div.getAttribute("class"));//"bd"alert(div.getAttribute("title"));//"Body text"alert(div.getAttribute("lang"));//"en"alert(div.getAttribute("dir"));//"ltr"

用这个方法可以获得标签自定义的属性:

<div id="myDiv" data-my_special_attribute="hello!"></div>var value = div.getAttribute("my_special_attribute");

另外,有两个特殊的属性,它们通过getAttribute访问或者通过获取元素属性的值得到的结果不同:
第一个是style:当通过getAttribute方法访问时,返回的是字符串,而通过元素的属性的方法访问时,返回的则是一个对象。
第二个是onclick这样的事件处理程序:通过getAttribute访问时,返回的是JS代码的字符串,而通过元素属性访问,返回的则是这个函数。

3、设置特性

div.setAttribute("id", "someOtherId");div.setAttribute("class", "ft");div.setAttribute("title", "Some other text");div.setAttribute("lang","fr");div.setAttribute("dir", "rtl");

4、attributes属性

Element类型是使用attributes属性的唯一的一个DOM节点类型。attributes属性中包含一个NamedNodeMap,是一个动态的集合。NamedNodeMap对象拥有下列方法:
getNamedItem(name):返回nodeName属性等于name的节点。
removeNamedItem(name):从列表中移除nodeName属性等于name的节点。setNamedItem(node):向列表中添加节点,以节点的nodeName属性为索引。
item(pos):返回位于pos位置的节点。

<div id="first" class="mydiv"> 萝卜 </div>// method 1var element = document.getElementById("first");var id = element.attributes.getNamedItem("class").nodeValue;console.log(id);// media// method 2var element = document.getElementsByTagName("div");var id = element[0].attributes.getNamedItem("class").nodeValue;console.log(id);// mydiv

5、创建元素

var div = document.createElement("div");// 为元素添加属性div.id = "myNewDiv";div.className = "box";// 将元素加入DOM树document.body.appendChild(div);// IE下:var div = document.createElement("<div id=\"myNewDiv\" class=\"box\"></div >");

6、元素的子节点

<ul id="myList">    <li>Item 1</li>    <li>Item 2</li>    <li>Item 3</li></ul>var element = document.getElementById("myList");var num = element.childNodes.length;console.log(num);// 7

在不是IE的浏览器下,上面这个ul包含了7个字节点:包括三个li节点和4个文本节点。正确的访问li的方法为:

for (var i=0, len=element.childNodes.length; i < len; i++){    if (element.childNodes[i].nodeType == 1){        //执行某些操作    }}// orvar ul = document.getElementById("myList");var items = ul.getElementsByTagName("li");

Text类型

文本节点由Text类型表示,包含的是纯文本内容。text节点具有一下的特征:
nodeType为3
nodeName为#text
nodeValue为节点包含的文本
parentNode是一个element
没有子节点

可以使用下列方法操作文本:
appendData(text) 将text添加至末尾
deleteData(offset, count) 从offset开始删除count个字符
insertData(offset, text) 从offset开始插入text
replaceData(offset, count, text) 用text替换从offset到offset+count的文本
splitText(offset) 从offset将文本分为两个
substringData(offset, count) 提取从offset到offset+count的文本

<!--没有文本节点--> <div></div><!--有1个文本节点--> <div> </div><!--有1个文本节点--> <div>Hello World!</div>
var textNode = div.firstChild; //  div.childNodes[0]div.firstChild.nodeValue = "Some other message";

修改文本节点时需要注意,此时的字符串要经过html编码,也就是说,有些符号会被转译:

//输出结果是"Some &lt;strong&gt;other&lt;/strong&gt; message" div.firstChild.nodeValue = "Some <strong>other</strong> message";

创建文本节点:

var textNode = document.createTextNode("<strong>Hello</strong> world!");// 创建文本节点并加入DOM中。var element = document.createElement("div");element.className = "message";var textNode = document.createTextNode("Hello world!");element.appendChild(textNode);document.body.appendChild(element);

规范化文本节点

该方法可以将多个文本节点合并:

var element = document.createElement("div");element.className = "message";var textNode = document.createTextNode("Hello world!");element.appendChild(textNode);var anotherTextNode = document.createTextNode("Yippee!");element.appendChild(anotherTextNode);document.body.appendChild(element);alert(element.childNodes.length);    //2element.normalize();alert(element.childNodes.length);    //1alert(element.firstChild.nodeValue); // "Hello world!Yippee!"

分割文本节点

该方法的作用和normalize刚好相反,是将一个文本节点分割为多个:

var element = document.createElement("div");element.className = "message";var textNode = document.createTextNode("Hello world!");element.appendChild(textNode);document.body.appendChild(element);var newNode = element.firstChild.splitText(5); alert(element.firstChild.nodeValue); //"Hello"alert(newNode.nodeValue); //" world!"alert(element.childNodes.length); //2

Comment类型

注释用Comment类型表示。特点:
nodeType值为8
nodeName为#comment
nodeValue为注释的内容
parentNode为Document或者Element
没有子节点

<div id="myDiv"><!--A comment --></div>// 访问var div = document.getElementById("myDiv");var comment = div.firstChild;alert(comment.data);    //"A comment"// 创建var comment = document.createComment("A comment ");

DocumentType类型

仅有Firefox Safari Opera支持。该类型包含了与文档doctype有关的信息。
nodeType:10
nodeName:doctype的名称
nodeValue:null
parentNode:Document
没有子节点

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"  "http://www.w3.org/TR/html4/strict.dtd">alert(document.doctype.name);        //"HTML"

Attr类型

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

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"

DOM操作技术

动态脚本

使用script元素可以向页面中插入JavaScript代码,一种方式是通过src链接外部文件,另一种方式就是在标签内直接写入代码。
动态脚本,指的是,页面加载时不存在,但是在将来的某一个时刻,通过修改DOM动态添加的脚本。动态创建脚本有两个方式:

1、动态加载外部的JS文件

<script type="text/javascript" src="client.js"></script>

创建这个节点的DOM代码如下所示:

var script = document.createElement("script");script.type = "text/javascript";script.src = "client.js";document.body.appendChild(script);// 函数封装function loadScript(url){   var script = document.createElement("script");   script.type = "text/javascript";   script.src = url;   document.body.appendChild(script);}// 加载文件loadScript("client.js");

2、行内方式

<script type="text/javascript">        function sayHi(){            alert("hi");        }</script>// DOM代码 不兼容IEvar script = document.createElement("script");script.type = "text/javascript"; script.appendChild(document.createTextNode("function sayHi(){alert('hi');}")); document.body.appendChild(script);// 兼容IEvar script = document.createElement("script"); script.type = "text/javascript";script.text = "function sayHi(){alert('hi');}"; document.body.appendChild(script);// 函数封装function loadScriptString(code){    var script = document.createElement("script");    script.type = "text/javascript";    try {        script.appendChild(document.createTextNode(code));    } catch (ex){        script.text = code;    }    document.body.appendChild(script);}// 函数调用loadScriptString("function sayHi(){alert('hi');}");

动态样式

<link rel="stylesheet" type="text/css" href="styles.css">// DOM代码var link = document.createElement("link");link.rel = "stylesheet";link.type = "text/css";link.href = "style.css";var head = document.getElementsByTagName("head")[0];head.appendChild(link);// 函数封装function loadStyles(url){    var link = document.createElement("link");    link.rel = "stylesheet";    link.type = "text/css";    link.href = url;    var head = document.getElementsByTagName("head")[0];    head.appendChild(link);}// 函数调用loadStyles("styles.css");// 第二种方式<style type="text/css">    body {        background-color: red;    }</style>// DOM方式var style = document.createElement("style"); style.type = "text/css";try{    style.appendChild(document.createTextNode("body{background-color:red}"));} catch (ex){    style.styleSheet.cssText = "body{background-color:red}";}var head = document.getElementsByTagName("head")[0];head.appendChild(style);// 函数封装function loadStyleString(css){    var style = document.createElement("style");    style.type = "text/css";try{    style.appendChild(document.createTextNode(css));} catch (ex){    style.styleSheet.cssText = css;}    var head = document.getElementsByTagName("head")[0];    head.appendChild(style);}// 函数调用loadStyleString("body{background-color:red}");
0 0
原创粉丝点击