JavaScript学习 七DOM

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript学习 七DOM相关的知识,希望对你有一定的参考价值。

 DOM(文档对象模型)是针对html和XML文档的一个API。DOM描绘了一个层次化的节点树。允许开发人员添加、移除、修改页面的某一部分。

节点层次

 文档节点是每个文档的根节点,文档元素是文档的最外层元素,文档中其他说有的元素都包含在文档元素中,每个文档只能有一个文档元素,在HTML 中,文档元素始终是<html> 元素,在XML 中没有预定义的元素,因此任何元素都可能成为文档元素。

每一段标记都可以通过树中的一个节点来表示:HTML 元素通过元素节点表示,特性(attribute)通过特性节点表示,文档类型通过文档类型节点表示,而注释则通过注释节点表示,总共有12 种节点类型。

 1.Node类型

DOM1 级定义了一个Node 接口,该接口将由DOM中所有节点类型实现。这个Node在javascript中是作为Node 类型实现的;JavaScript 中所有节点都继承自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)

 可以用节点的nodeType属性和上面的常量比较,如果相等,则说明节点是 该类型的元素。由于IE没有公开Node类型的构造函数,所以为了确保跨浏览器兼容,最好还是将nodeType属性与数字值进行比较。

if(someNode.nodeType == 1){  //Node.ELEMENT_NODE
    alert("Node is an element");
}

 

 可以使用nodeName 和 nodeValue 者两个属性来了解节点的具体信息,对于元素节点,nodeName中保存的始终都是元素的表签名,而nodeValue 则始终为null。

每一个节点都保存者一个childNodes 属性,其中保存着一个NodeList对象。NodeList是一种类似于数组的对象,用于保存一组有序的节点。NodeList 对象的独特之处在于,它实际上是基于DOM结构动态执行查询的结果,因此DOM结构的变化能够自动反应在NodeList 对象中。

可以使用方括号或者item方法来访问NodeList中的对象。

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

 

可以使用Array.prototype.slice()方法将NodeList转换成普通的ArrayList对象。

var arrayOfNodes = Array.prototype.slice.call(someNode.childNodes, 0);

 

每个节点还有 prentNode、previousSibling、nextSibling、firstChild、lastChild等属性。顾名思义,不再一一介绍。

方法

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

使用insertBefore()方法可以把节点方法childNodes 列表中某个特定的位置上。接收两个参数:要插入的节点和作为参照的节点。插入节点后,被插入的节点会变成参照节点的前一个兄弟节点(previousSibling),同时被方法返回。如果参照节点是null, 则insertBefore() 与 appendChild() 执行相同的操作。

 replaceChild()方法接收两个参数:要插入的节点和要替换的节点。要替换的节点将由这个方法返回并从文档树中被移除,同时由要插入的节点占据其位置。

removeChild()方法接收一个参数,即要移除的节点。被移除的节点将成为方法的返回值。

cloneNode() 用于创建调用这个方法的节点的一个完全相同的副本。该方法接收一个布尔值参数,表示是否执行深复制。

2.Document类型

JavaScript 通过Document 类型表示文档,在浏览器中,document 对象是HTMLDocument的一个实例,表示整个HTML页面。而且document对象是window对象的一个属性,因此可以作为全局对象来访问。

document 的 nodeType 为9, nodeName 为“#document”,nodeValue 为null parentNode 为null,ownerDocument为null。

Document 节点的子节点可以是DocumentType、Element、ProcessingInstruction 或 Comment,但还是有两个内置的访问其子节点的快捷方式。

第一个就是documentElement 属性,该属性始终指向 HTML 页面中的<html> 元素。另一个就是body 属性,直接指向<body> 元素。

document 对象有一些标准的Document 对象所没有的属性。这些属性提供了document 对象所表现的页面的一些信息。

第一个属性是 title,包含者<title> 元素中的文本----显示在浏览器窗口的标题栏或标签页上。通过这个属性可以取得当前页面的标题,也可以修改当前页面的标题并反应在浏览器的标题栏中。

URL属性中包含页面完整的URL,domain 属性中包含页面的域名,而referrer 属性中则保存着联街道当前页面的哪个页面的URL。在没有来源页面的情况下,referrer 属性中可能会包含空字符串。所有这些信息都存在于请求的HTTP 头部,只不过是通过这些属性让我们能够在JavaScript中访问他们而已。

document提供了两个方法用于查找某个或某组元素的引用:getElementById() 和 getElementsByTagName()。

getElementsByTagName() 函数返回的是包含0或多个元素的 NodeList。在HTML中,这个方法会返回一个HTMLCollection 对象,作为一个动态集合,该对象与NodeList 非常类似。

getElementsByName() 方法是HTMLDocument 特有的方法,返回带有给定name 特性的所有元素。

document对象还有一些特殊的集合,这些集合都是HTMLCollection对象,为访问文档常用部分提供了快捷方式。

  • document.anchors, 包含文档中所有带name特性的<a> 元素。
  • document.forms,包含文档中所有的<form> 元素。与  document.getElementsByTagName("form") 得到的结果相同。
  • document.images,包含文档中所有的<img> 元素,与 document.getElementsByTagName("img") 得到的结果相同。
  • document.links,包含文档中所有带href特性的<a>元素。

3.Element类型

  • nodeType 值为 1
  • nodeName 值为元素表签名
  • nodeValue 值为 null
  • parentNode 可能是 Document或 Element
  • 其子节点可能是 Element、Text、Comment、ProcessingInstruction、CDATASection 或 EntityReference。

要访问元素的标签名,可以使用nodeName属性,也可以使用tagName 属性;这两个属性会返回相同的值。

所有的HTML元素都由HTMLElement 类型表示,不是直接通过这个类型也是通过它的子类型来表示。HTMLElement 类型直接继承自Element 并添加了一些属性。添加的这些属性分别对应于每个HTML都存在的下列标准特性:

  • id,元素在文档中的唯一标识符
  • title,有关元素的附加说明信息,一般通过工具提示条显示出来
  • lang,元素内容的语言代码,很少使用
  • dir,语言的方向,值为“ltr”(left-to-right,从左向右)或“rtl”(right-to-left,从右向左),也甚少使用。
  • className,与元素class特性对应,即为元素制定的CSS 类。没有将这个属性命名为class,是因为class 是ECMAScript的保留字。
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>study</title>
    </head>
    <body>
    <div id="myDiv" class="bd" title="Body text" lang="en" dir="rtl">good morning</div>
        <script type="text/javascript">
        var div = document.getElementById("myDiv");
        alert("id=" + div.id + ", class=" + div.className + ", title=" + div.title + ", lang=" + div.title + ", dir=" + div.dir);  //id=myDiv, class=bd, title=Body text, lang=Body text, dir=rtl
        </script>
    </body>
</html>

 getAttribute()方法也可以取得属性内容,也可以取得自定义的特性。参数传递属性名称,不去分大小写。

在通过JavaScript 以编程方式操作DOM 时,开发人员经常不使用getAttribute(),而是只使用对象的属性。只有在取得自定义特性值的情况下,才会使用getAttribute() 方法。

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

removeAttribute() 方法用于彻底删除元素的特性。调用这个方法不仅会清除特性的值,而且也会从元素中完全删除特性。

Element 类型是使用attributes 属性的唯一一个DOM 节点类型。attributes 属性中包含一个NamedNodeMap,是一个动态集合。元素的每一个特性都是一个Attr节点表示,每个节点都保存在NamedNodeMap对象中。NamedNodeMap对象拥有下列方法:

  • getNamedItem(name):返回nodeName属性等于name的节点;
  • removeNamedItem(name):从列表中移除nodeName属性等于name的节点;
  • setNamedItem(node):向列表中添加节点,以节点的nodeName 属性为索引;
  • item(pos):返回位于数字pos位置处的节点。

attributes属性中包含一系列节点,每个节点的nodeName 就是特性的名称,而节点的 nodeValue 就是特性的值。要取得元素的id特性,可以使用以下代码。

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

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

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

 

 一般来说,因为attributes 的方法不够方便,因此开发人员更多的会使用 getAttribute()、setAttributes()、removeAttributes()方法。

创建元素,使用document.creatElement()可以创建新元素,这个方法只接收一个参数,即要创建元素的标签名,

var div = document.createElement("div");
div.id = "myNewDiv";
div.className = "box";

 4.Text类型

  • nodeType 值为3;
  • nodeName 值为 “#text”;
  • nodeValue 值为节点所包含的文本;
  • parentNode是一个Element;
  • 不支持(没有)子节点。

可以通过nodeValue 属性或者 data 属性来访问Text 节点中包含的文本,这两个属性中包含的值相同。对nodeValue的修改也会通过data反映出来,反之亦然。

可以使用下列方法来操作节点中的文本。

  • 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 为止处的字符串。

文本节点还有一个length 属性,保存着节点中字符的数目。

创建文本节点,可以使用 document.createTextNode()创建新文本节点,这个方法接受一个参数----要插入的文本。

 

DOM操作技术

 操作表格

<table> 元素是 HTML中最复杂的结构之一,要想创建表格,一般都必须设计表示表格行、单元格、表头等方面的标签。由于涉及的标签多,因此使用核心的DOM方法创建和修改表格往往都免不了要编写大量的代码。为了方便构建表格,HTML DOM 还为<table>、<tbody>和<tr>元素添加了一些属性和方法。

为<table>元素添加的属性和方法:

  • caption:保存着对<caption>元素的指针;
  • tBodies:是一个<tbody> 元素的HTMLCollection。
  • tFoot:保存着对 <tfoot>元素的指针;
  • tHead:保存着对<thead>元素的指针;
  • rows:是一个表格中所有行的HTMLCollection;
  • createTHead():创建<thead> 元素,将其放到表格中,返回引用;
  • createTFoot():创建<tfoot> 元素,将其放到表格中,返回引用。
  • createCaption():创建<caption> 元素,将其放到表格中,返回引用。
  • deleteTHead():删除<thead>元素。
  • deleteTFoot():删除<tfoot>元素。
  • deleteCaption():删除<caption> 元素。
  • deleteRow(pos):删除指定位置的行。
  • insertRow(pos):向rows集合中的制定位置插入一行。

为<tbody> 元素添加的属性和方法:

  • rows:保存着<tbody>元素中的行的HTMLCollection。
  • deleteRow(pos):删除指定位置的行。
  • insertRow(pos):向rows集合中的制定位置插入一行,返回对新插入行的引用。

为<tr>元素添加的属性和方法:

  • cells:保存着<tr>元素中单元格的HTMLCollection。
  • deleteCell(pos):删除制定位置的单元格。
  • insertCell(pos):向cells集合中的指定位置插入一个单元格返回对新单元格的引用。
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>study</title>
    </head>
    <body>
    
        <script type="text/javascript">
        var table = document.createElement("table");
        table.border = 1;
        table.width = "100%";

        //create tbody
        var tbody = document.createElement("tbody");
        table.appendChild(tbody);

        //first row
        tbody.insertRow(0);
        tbody.rows[0].insertCell(0);
        tbody.rows[0].cells[0].appendChild(document.createTextNode("Cell 1, 1"));
        tbody.rows[0].insertCell(1);
        tbody.rows[0].cells[1].appendChild(document.createTextNode("Cell 1, 2"));

        //second row
        tbody.insertRow(1);
        tbody.rows[1].insertCell(0);
        tbody.rows[1].cells[0].appendChild(document.createTextNode("Cell 2, 1"));
        tbody.rows[1].insertCell(1);
        tbody.rows[1].cells[1].appendChild(document.createTextNode("Cell 2, 2"));

        document.body.appendChild(table);
        
        </script>
    </body>
</html>

 

NodeList

NodeList、NamedNodeMap 和 HTMLCollection 三个集合都是动态的集合,每当文档结构发生变化是,他们都会更新。因此他们始终都会保存着最新、最准确的信息。从本质上说,所有NodeList对象都是在访问DOM文档时实时运行查询。

var divs = document.getElementsByTegName("div"), i, div;

for(i = 0; i < divs.length; i++){
    div = document.createElement("div");
    document.body.appendChild(div);
}

 

由于divs是动态集合,所以上面代码会导致无限循环,解决方法是把divs.length保存到另一个变量中进行缓存。

一般来说,应该尽量减少访问NodeList的次数。

小结

DOM是语言中立的 API,用于访问HTML 和XML 文档。DOM1级将HTML和XML 文档形象地看做一个层次化的节点树,可以使用JavaScript来操作这个节点树,进而改变底层文档的外观和结构。

  • 最基本的节点类型是Node, 用于抽象地表示文档中一个独立的部分;所有其他类型都继承自Node。
  • Document 类型表示整个文档,是一组分层节点的根节点,在JavaScript 中, document对象是Document的一个实例。使用document 对象,有很多中方式可以查询和取得节点。
  • Element 节点表示文档中所有HTML 或 XML 元素,可以用来操作这些元素的内容和特性。
  • 另外还有一些节点类型,分别表示文本内容、注释、文档类型、CDATA区域和文档片段。

 

以上是关于JavaScript学习 七DOM的主要内容,如果未能解决你的问题,请参考以下文章

第910期No JQuery! 原生JavaScript操作DOM

JavaScript-Runoob-JS HTML DOM :DOM 节点列表

轻松学习JavaScript十八:DOM编程学习之DOM简单介绍

JavaScript DOM编程艺术-学习笔记(第七章)

轻松学习JavaScript二十七:DOM编程学习之事件模型

JavaScript DOM编程艺术-学习笔记(总结一)