小白读《JavaScript高级程序设计》DOM基础部分

DOM

DOM(文档对象模型)是针对HTML和XML文档 的一个API(应用程序编程接口)。

节点层次

DOM可以将任何HTML或XML文档描绘成一个由多层节点构成的结构。
每个文档只能有一个文档元素,在HTML页面中,文档元素始终都是<html>元素。
总共有12种节点类型:
示例图片3

Node类型

DOM1级定义了一个Node接口,该接口将由DOM中的所有节点类型实现。
JavaScript中的所有节点类型都继承自Node类型。
nodeType属性:用于表明节点的类型。
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)。

nodeName和nodeValue属性

了解节点的具体信息。

节点关系

每个节点都有一个childNodes属性,其中保存着一个NodeList对象。
NodeList对象:一种类数组的对象(不是数组,但是有length)。

通用的将NodeList对象转为数组的方法:

function converToArray(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属性,该属性指向文档树中的父节点。
对于同胞节点,通过使用列表中每个节点的previousSibling(上一个节点)和nextSibling(下一个节点)属性,可以访问同一列表中的其他节点。

父节点的firstChild和lastChild属性分别指向其childNodes列表中的第一个和最后一个节点。
示例图片4

hasChildNodes()方法:返回是否有字节点,Boolean类型。
每个节点都有的属性:ownerDocument:该属性指向表示整个文档的文档节点。

操作节点

appendChild()方法:用于向childNodes列表的末尾添加一个节点。
appendChild()返回新增的节点。
如果appendChild()中的节点已经是文档的一部分了,就将该节点从原来位置转移到新位置。

insertBefore()方法:接受两个参数:要插入的节点和作为参照的节点。
插入节点后,被插入的节点会变成参照节点的前一个同胞节点(previousSibling),同时被方法返回。
如果参照节点为null,则同appendChild()方法。

扫描二维码关注公众号,回复: 3922842 查看本文章

replaceChild()方法:接受两个参数:要插入的节点和要替换的节点。

removeChild()方法:接受一个参数,即是要移除的节点。

其他方法

两个所有类型的节点都有的方法:
cloneNode():用于创建调用这个方法的节点的一个完全相同的副本。
接受一个布尔值参数,表示是否执行深复制。
true:深复制,复制节点及其整个子节点树。
false:浅复制,只复制节点本身。

normalize():这个方法唯一的作用就是处理文档树中的文本节点。
删除文本,合并相邻文本节点。

Document类型

Document节点具有下列特征:

  • nodeType的值为9;
  • nodeName的值为"#document";
  • nodeValue的值为null;
  • parentNode的值为null;
  • ownerDocument的值为null;
  • 其子节点可能是一个DocumentType(最多一个)、Element(最多一个)、ProcessingInstruction或Comment。

文档的子节点

documentElement属性能更快捷、更直接地访问HTML中的<html>元素。
获取body元素:document.body
获取<!DOCTYPE>标签:document.doctype

文档信息

类似的还有:
document.title;
document.URL;(http获得的页面的URL)
document.domain(域名)

查找元素

两个方法:

  • getElementById():通过id属性(怪癖:name属性也会被调用)
  • getElementsByTagName():通过标签名。

HTMLDocument类型独有的方法:
getElementsByName():通过name属性。

特殊集合

都是HTMLCollection对象:

  • document.anchors:所有带name特性发<a>元素。
  • document.applets:文档中所有的<applet>元素。
  • document.forms
  • document.images
  • document.links:文档中所有带href特性的<a>元素。

DOM一致性检测

document.implementation规定了一个方法:hasFeature()。

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

文档写入

4个方法:

  • write():接受一个字符串
  • writeln():接受一个字符串
  • open():打开网页的输出流
  • close():关闭网页的输出流

Element类型

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

在HTML中,标签名始终都以大写表示,而在XML(有时候也包括XHTML)中,标签名则始终会与源代码中的保持一致。

element.tagName.toLowerCase() == "div"

HTML元素

所有HTML元素都由HTMLElement类型表示。

  • id,元素在文档中的唯一标识符。
  • title,有关元素的附加说明信息,一般通过工具提示条显示出来。
  • lang,元素内容的语言代码,很少使用。
  • dir,语言的方向,ltr、rtl。
  • className,与元素的class特性对应。

取得特性

每个元素都有一个或多个特性,这些特性的用途是给出相应元素或其内容的附加信息。
操作特性的DOM方法主要有三个:

  • getAttribute():参数是特性名的字符串。
  • setAttribute():同上
  • removeAttribute():同上

两类特殊的特性:style和onclick。

设置特性

setAttribute(),替换或者创建。
这个方法设置的特性名会统一转换为小写形式。

attributes属性

Element类型是使用attributes属性的唯一一个DOM节点类型。
attributes属性中包含一个NameNodeMap。
NameNodeMap对象拥有的方法:

  • getNameItem(name):返回nodeName属性等于name的节点。
  • removeNamedItem(name)
  • setNamedItem(name)
  • item(pos)

为特性设置新值:

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

创建元素

document.createElement()方法。
参数是要创建元素的标签名。HTML忽略大小写,XML区分大小写。

把新元素添加到文档树:
appendChild()、insertBefore()、replaceChild()。

注意点:

  1. 不能设置动态创建的<iframe>元素的name特性。
  2. 不能通过表单的reset()方法重设动态创建的<input>元素。
  3. 动态创建的type特性值为"reset"的<button>元素重设不了表单。
  4. 动态创建的一批name相同的单选框彼此毫无关系。

元素的子节点

元素可以有任意数目的子节点和后代节点。
这些子节点有可能是元素、文本节点、注释或处理指令。

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

还有个length属性

创建文本节点

document.createTextNode()方法。

规范化文本节点

normalize()方法
父节点使用,子节点中多个文本节点合并为一个。

分割文本节点

splitText()方法。
参数:一个数值代表要分割的位置。
把一个节点分为两个。

Comment类型

  • nodeType的值为8
  • nodeName的值为"#comment"
  • nodeValue的值是注释的内容
  • parentNode 可能是Document或Element
  • 不支持(没有)子节点。

Coment类型与Text类型继承自相同的基类(所以,你懂的,很多前面提到的方法可以用)。
document.createComment()

CDATASection类型

只针对基于XML的文档。类似Comment,nodeType值为4。

DocumentType类型

并不常用。包含着与文档的doctype有关的所有信息。

  • nodeType的值为10
  • nodeName的值为doctype的名称
  • nodeValue的值为null
  • parentNode是Document
  • 不支持(没有)子节点

DocumentFragment类型

"轻量级"文档。

  • nodeType值11
  • nodeName:"#document-fragment"
  • nodeValue:null
  • parentNode:null
  • 子节点可以是:Element、ProcessingInstruction、Comment、Text、CDATASection或EntityReference。

document.createDocumentFragment()方法。

Attr类型

  • nodeType:2
  • nodeName:特性的名称
  • nodeValue:特性的值
  • parentNode:null
  • 在HTML中不支持(没有)子节点。
  • 在XML中子节点可以是Text或EntityReference。

3个属性:name、value、specified(布尔值,区别在代码中指定的还是默认的)。
代码演示:

var attr = document.createAttribute("align");
attr.value = "left";
element.setAttributeNode(attr);
alert(element.atrributes["align"].value);		//"left"
alert(element.getAtrributeNode("align").value);		//"left"
alert(element.getAtrribute("align"));				//"left"

DOM操作技术

浏览器中充斥着隐藏的陷阱和不兼容问题。

动态脚本

在页面加载时不存在,但将来的某一时刻通过修改DOM动态添加的脚本。
创建动态脚本两种方式:插入外部文件和直接插入JavaScript代码。
封装的方法实现加载外部JavaScript文件:

function loadScript(url) {
	var script = document.createElement("script");
	script.type = "text/javascript";
	script.src = url;
	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);
}

动态样式

封装的加载样式的方法:

function loadStyles(url) {
	var link = document.createElement("link");
	link.rel = "stylessheet";
	link.type = "text/css";
	link.href = url;
	var head = document.getElementsByTagName("head")[0];
	head.appendChild(link);
}

直接写代码封装的方法:

function loadStylesString(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);
}

操作表格

<table>元素是HTML中最复杂的结构之一。
正常写需要冗长的代码。
使用HTMLDOM提供的方法可以简化。
例:要创建下面结构:

<table border="1" width="100%">
	<tbody>
		<tr>
			<td>Cell 1,1</td>
			<td>Cell 2,1</td>
		</tr>
		<tr>
			<td>Cell 1,2</td>
			<td>Cell 2,2</td>
		</tr>
	</tbody>
</table>

DOM代码:

//创建table
var table = document.createElement("table");
table.border = 1;
table.width = "100%";

//创建tbody
var tbody = document.createElement("tbody");
table.appendChild(tbody);
//创建第一行
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 2,1"));
//创建第二行
tbody.insertRow(1);
tbody.rows[1].insertCell(0);
tbody.rows[1].cells[0].appendChild(document.createTextNode("Cell 1,2"));
tbody.rows[1].insertCell(1);
tbody.rows[1].cells[1].appendChild(document.createTextNode("Cell 2,2"));
//将表格添加到文档主体中
document.body.appendChild(table);

使用NodeList

三个”动态的”集合:NameNodeMap、HTMLCollection和NodeList。
每当文档结构发生变化时,都会得到更新。

猜你喜欢

转载自blog.csdn.net/canxuezhang/article/details/83540809