第10章 DOM
1.DOM(文档对象模型)是针对 HTML 和 XML 文档的一个 API(应用程序编程接口),描绘了一个层次化的节点树,允许开发人员添加、移除和修改页面的某一部分。
2.每个节点都有一个 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)
(1)使用 nodeName 和 nodeValue 属性了解节点的具体信息。
(2)childNodes 属性保存着一个 NodeList 对象,一种类数组对象,用于保存一组有序的节点,可以通过位置来访问这些节点,有 length 属性。
(3) parentNode 属性,指向文档树中的父节点。
(4)使用列表中每个节点的 previousSibling 和 nextSibling 属性,访问同一列表中的其他节点。
(5)hasChildNodes():用于确定节点是否包含一或多个子节点,比查询 childNodes 列表的 length 属性更简单。
(6)ownerDocument属性,指向表示整个文档的文档节点,不必在节点层次中通过层层回溯到达顶端,直接访问文档节点。
(7)appendChild():向 childNodes 列表的末尾添加一个节点,返回新增的节点
(8)insertBefore():接受两个参数:要插入的节点和作为参照的节点。
(9)replaceChild():接受的两个参数是:要插入的节点和要替换的节点。
(10)removeChild():接受一个参数,即要移除的节点。
(11)cloneNode():创建调用这个方法的节点 的一个完全相同的副本,接受一个布尔值参数,表示是否执行深复制(复制节点及其整个子节点树)。
3.Document类型:文档类型,具有下列特征:
- nodeType 的值为 9;
- nodeName 的值为"#document";
- nodeValue 的值为 null;
- parentNode 的值为 null;
- ownerDocument 的值为 null;
- 其子节点可能是一个 DocumentType(最多一个)、Element(最多一个)、ProcessingInstruction或 Comment。
(1)documentElement属性:指向 HTML 页面中的<html>元素
body 属性:直接指向<body>元素
(2)title属性:包含着<title>元素中的文本——显示在浏览器窗口的标题栏或标签页上。
(3)URL属性:包含页面完整的 URL(即地址栏中显示的 URL)
domain 属性:包含页面的域名,只有 domain 可以设置,不能将domain设置为 URL 中不包含的域。将每个页面的 document.domain 设置为相同的值,可以让来自不同子域的页面进行通信(应对跨域问题),如果域名一开始是“松散的”(loose),那么不能将它再设 置为“紧绷的”(tight)。
referrer属性:保存着链接到当前页面的那个页面的 URL
(4)getElementById():接收一个参数:要取得的元素的 ID。如果找到相应的元素则 返回该元素,否则返回null。只返回文档中第一次出现的元素。
getElementsByTagName():接受一个参数,要取得元素的标签名,返回包含零或多个元素的 HTMLCollection 对象,可以 使用方括号语法或 item()方法来访问 HTMLCollection 对象中的项,使用namedItem()方法可以通过元素的 name 特性取得集合中的项。
getElementsByName():返回带有给定 name 特性的所有元素,最常使用来取得单选按钮,
(5)document 对象还有一些特殊的集合:
- document.anchors:包含文档中所有带 name 特性的<a>元素;
- document.forms:包含文档中所有的<form>元素,与 document.getElementsByTagName("form")得到的结果相同;
- document.images:包含文档中所有的<img>元素,与 document.getElementsByTagName("img")得到的结果相同;
- document.links:包含文档中所有带 href 特性的<a>元素。
(6)document.implementation 属性的hasFeature()方法接受两个参数:要检测的 DOM 功能的名称及版本号,用来检测浏览器实现了 DOM 的哪些部分。
-
//如果浏览器支持给定名称和版本的功能,则该 方法返回 true var hasXmlDom = document.implementation.hasFeature("XML", "1.0");
(7)将输出流写入到网页中
- write():接受一个字符串参数,即要写入到输出流中的文本,会原样写入。如果在文档加载结束后再调用 document.write(),那么输出的内容将会重写整个页面。
- writeln():接受一个字符串参数,即要写入到输出流中的文本,会在字符串的末尾添加一个换行符(\n)。
- open():打开网页的输出流。
- close():关闭网页的输出流。
4.Element类型,提供了对元素标签名、子节点及特性的访问,具有以下特征:
- nodeType 的值为 1;
- nodeName 的值为元素的标签名;
- nodeValue 的值为 null;
- parentNode 可能是 Document 或 Element;
- 其子节点可能是 Element、Text、Comment、ProcessingInstruction、CDATASection 或EntityReference。
(1)所有 HTML 元素都由 HTMLElement 类型表示,HTMLElement 类型直接继承自 Element ,每个 HTML 元素中都存在的下列标准特性:
- id:元素在文档中的唯一标识符。
- title:有关元素的附加说明信息,一般通过工具提示条显示出来。
- lang:元素内容的语言代码,很少使用。
- dir:语言的方向,值为"ltr"(left-to-right,从左至右)或"rtl"(right-to-left,从右至左),也很少使用。
- className:与元素的 class 特性对应,即为元素指定的 CSS 类。
(2)操作特性的 DOM 方法主要有三个:
- getAttribute():取得特性的值
- setAttribute():接受两个参数:要设置的特性名和值,如果特性已经存在,setAttribute()会以指定的值替换现有的值,如果特性不存在,setAttribute() 则创建该属性并设置相应的值。
- removeAttribute():彻底删除元素的特性。
(3)Element 类型是使用 attributes 属性的唯一一个 DOM 节点类型,attributes 属性中包含一个NamedNodeMap保存着元素的每一个特性,NamedNodeMap 对象拥有下列方法:
- getNamedItem(name):返回 nodeName 属性等于 name 的节点;
- removeNamedItem(name):从列表中移除 nodeName 属性等于 name 的节点;
- setNamedItem(node):向列表中添加节点,以节点的 nodeName 属性为索引;
- item(pos):返回位于数字 pos 位置处的节点。
(4)使用 document.createElement()方法可以创建新元素,只接受一个参数,即要创建元素的标签名。
2.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 属性:保存着节点中字符的数目
- normalize():在一个包含两个或多个文本节点的父元素上调用,将所有文本节点合并成一个 节点,结果节点的 nodeValue 等于将合并前每个文本节点的 nodeValue 值拼接起来的值。
5.Comment类型,具有下列特征:
- nodeType 的值为 8;
- nodeName 的值为"#comment";
- nodeValue 的值是注释的内容;
- parentNode 可能是 Document 或 Element;
- 不支持(没有)子节点。
-
//使用 document.createComment()并为其传递注释文本创建注释节点 var comment = document.createComment("A comment ");
6.DocumentFragment类型,文档片段 (document fragment)是一种“轻量级”的文档,可以包含和控制节点,但不会像完整的文档那样占用额外的资源,具有下列特征:
- nodeType 的值为 11;
- nodeName 的值为"#document-fragment";
- nodeValue 的值为 null;
- parentNode 的值为 null;
- 子节点可以是 Element、ProcessingInstruction、Comment、Text、CDATASection 或EntityReference。
-
/*为<ul>元素添加 3 个列表项。 如果逐个地添加列表项,将会导致浏览器反复渲染(呈现)新信息。 为避免这个问题,用一个文档片段来保存创建的列表项,然后再一次性将它们添加到文档中。*/ //使用 document.createDocumentFragment()创建文档片段 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))); fragment.appendChild(li); } ul.appendChild(fragment);
7.Attr类型,特性节点具有下列特征:
- nodeType 的值为 2;
- nodeName 的值是特性的名称;
- nodeValue 的值是特性的值;
- parentNode 的值为 null;
- 在 HTML 中不支持(没有)子节点;
- 在 XML 中子节点可以是 Text 或 EntityReference。
-
//使用 document.createAttribute()并传入特性的名称创建新的特性节点 var attr = document.createAttribute("align"); attr.value = "left"; //setAttributeNode()将新创建的特性添加到元素中 element.setAttributeNode(attr); //attributes 属性、getAttributeNode()方法以及 getAttribute()方法都可以访问特性 alert(element.attributes["align"].value); //"left" alert(element.getAttributeNode("align").value); //"left" alert(element.getAttribute("align")); //"left"
8.DOM 操作技术
(1)动态脚本:在页面加载时不存在, 但将来的某一时刻通过修改 DOM 动态添加的脚本。
-
//添加动态脚本的兼容方法 function loadScriptString(code){ var script = document.createElement("script"); script.type = "text/javascript"; try { //标准的 DOM 文本节点方法 script.appendChild(document.createTextNode(code)); } catch (ex){ script.text = code; } document.body.appendChild(script); } loadScriptString("function sayHi(){alert('hi');}");
(2)动态样式:在页面刚加载时不存在,在页面加载完成后动态添加到页面中的样式。
-
//添加动态样式的兼容方法 function loadStyles(url){ var link = document.createElement("link"); ink.rel = "stylesheet"; link.type = "text/css"; link.href = url; var head = document.getElementsByTagName("head")[0]; head.appendChild(link); } loadStyles("styles.css");
(3)操作表格
1⃣️为<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 集合中的指定位置插入一行。
2⃣️为<tbody>元素添加的属性和方法:
- rows:保存着<tbody>元素中行的 HTMLCollection。
- deleteRow(pos):删除指定位置的行。
- insertRow(pos):向 rows 集合中的指定位置插入一行,返回对新插入行的引用。
3⃣️为<tr>元素添加的属性和方法:
- cells:保存着<tr>元素中单元格的 HTMLCollection。
- deleteCell(pos):删除指定位置的单元格。
- insertCell(pos):向 cells 集合中的指定位置插入一个单元格,返回对新插入单元格的引用。
-
//创建 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);
(4)所有 NodeList 对象都是在访问 DOM 文 档时实时运行的查询,应该尽量减少访问 NodeList 的次数,因为每次访问 NodeList,都会运行一次基于文档的查询,可以考虑将从 NodeList 中取得的值缓存起来。