本文共--字 阅读约--分钟 | 浏览: -- Last Updated: 2020-04-08
DOM
(Document Object Model 文档对象模型)是针对HTML
和XML
文档的一个API
(应用程序编程接口)。DOM
描绘了一个层次化的节点树,允许开发人员添加、移除和修改页面的某一部分。DOM
脱胎于Netscape 及微软公司创始的DHTML
(动态HTML
),但现在它已经成为表现和操作页面标记的真正的跨平台、语言中立的方式。
DOM1
级定义了一个Node
接口,该接口将由DOM
中的所有节点类型实现。每个节点都有一个nodeType
属性,用于表明节点的类型。节点类型由在Node 类型中定义的下列12 个数值常量来表示,任何节点类型必居其一:
每个节点都有一个childNodes
属性,其中保存着一个NodeList
对象。NodeList
是一种类数组对象,可以通过下标访问,有length
属性,但它并不是Array
的实例。NodeList
对象的独特之处在于,**它实际上是基于DOM
结构动态执行查询的结果,因此DOM
结构的变化能够自动反映在NodeList
对象中。**我们常说,NodeList
是有生命、有呼吸的对象,而不是在我们第一次访问它们的某个瞬间拍摄下来的一张快照。
如何访问保存在NodeList
中的节点,可以通过方括号,也可以使用item()
方法。
var firstChild = someNode.childNodes[0];
var secondChild = someNode.childNodes.item(1);
var length = someNode.childNodes.length;
使用Array.prototype.slice()
方法可以将NodeList
对象转换为数。
var arrayOfNodes = Array.prototype.slice.call(someNode.childNodes,0);
parentNode
:该属性指向文档树中的父节点previousSibling
:该属性指向文档书中的前一个兄弟节点,第一个节点的previousSibling
属性值为null
nextSibling
:该属性指向文档书中的前一个兄弟节点,最后一个节点的nextSibling
属性值为null
firstChild
:该属性指向父节点的第一个子节点lastChild
:该属性指向父节点的最后一个子节点appendChild
:用于向childNodes
列表的末尾添加一个节点,返回新增的节点,并且更新DOM,并且该节点自动作为lastChild
存在。如果传入到appendChild
中的节点已经是文档的一部分了,那么该节点就会成为父节点的lastChild
insertBefore
:把节点放在childNodes
列表中某个参照节点的前面,接受两个参数:要插入的节点和作为参照的节点,返回被插入的节点。如果参照节点是null
,则insertBefore
与appendChild
执行相同的操作。
replaceChild
:接受两个参数,要插入的节点和要替换的节点。要替换的节点将由这个方法返回并从文档树中被移除,同时由要插入的节点占据其位置。在使用replaceChild
插入一个节点时,该节点的所有关系指针都会从被它替换的节点复制过来。
removeChild
:这个方法接受一个参数,即要移除的节点。被移除的节点将成为方法的返回值。
cloneNode
:用于创建调用这个方法的节点的一个完全相同的副本,接受一个布尔值参数,表示是否执行深复制。为true
时执行深复制,复制节点及其整个子节点树;反之,执行浅复制,只复制节点本身。复制后返回的节点副本属于“文档碎片”,除非通过appendChild
、insertBefore
或replaceChild
将它添加到文档中。normalize
:由于解析器的实现或DOM
操作等原因,可能会出现文本节点不包含文本,或者接连出现两个文本节点的情况。当在某个节点上调用这个方法时,就会在该节点的后代节点中查找上述两种情况。如果找到了空文本节点,则删除它;如果找到相邻的文本节点,则将它们合并为一个文本节点。var deepList = myList.cloneNode(true);
alert(deepList.childNodes.length); //3(IE < 9)或7(其他浏览器)
var shallowList = myList.cloneNode(false);
alert(shallowList.childNodes.length); //0
cloneNode
方法不会复制DOM
节点中的JavaScript
属性,例如事件处理程序等。这个方法只复制特性,深复制情况下还复制子节点,其他一切都不会复制。
document
对象:在浏览器中,document
对象是HTMLDocument
(继承自Document
类型)的一个实例,表示整个HTML
页面。而且,document
对象是window
对象的一个属性,因此可以将其作为全局对象来访问。通过这个文档对象,不仅可以取得与页面有关的信息,而且还能操作页面的外观及其底层结构。Document
节点具有下列特征: nodeType
的值为9;nodeName
的值为"#document"
;nodeValue
的值为null
; parentNode
的值为null
;
document
对象的属性:
//取得对<html>的引用
var html = document.documentElement;
//取得对<body>的引用
var body = document.body;
//取得对<DOCTYPE>文档类型的引用
var doctype = document.doctype;
//取得文档标题
var originalTitle = document.title;
//设置文档标题
document.title = "New page title";
//取得完整的URL,不可设置
var url = document.URL;
//取得域名,可设置,但是不能随便设置
var domain = document.domain;
//假设页面来自p2p.wrox.com 域
document.domain = "wrox.com"; // 成功
document.domain = "nczonline.net"; // 出错! 只能省略域名
//取得来源页面的URL,不可设置
var referrer = document.referrer;
getElementById
:接收一个参数:要取得的元素的ID
。如果找到则返回该元素,如果不存在,则返回null
。如果页面中多个元素的ID 值相同,只返回文档中第一次出现的元素。
getElementsByTagName
:接受一个参数,即要取得元素的标签名,返回一个HTMLCollection
对象,作为一个“动态”集合,返回所有的标签元素组成的类数组。这个HTMLCollection
对象还有一个方法namedItem
,可以通过元素的name
特性取得集合中的项,而不用通过下标。例如:
<img src="myimage.gif" name="myImage">
<script>
var images = document.getElementsByTagName("img");
var myImage = images.namedItem("myImage");
// HTMLCollection 还支持按名称访问项
var myImage = images["myImage"];
</script>
getElementsByClassName
:接受一个参数,即要取得元素的类名,返回一个HTMLCollection
对象。在通过元素调用这些方法时,除了搜索起点是当前元素之外,其他方面都跟通过**document
**调用这个方法相同,因此结果只会返回当前元素的后代。
var ul = document.getElementById("myList");
var items = ul.getElementsByTagName("li");
document.createElement()
创建元素:接受一个参数,即要创建元素的标签名,返回一个“文档碎片”。document.anchors
,包含文档中所有带name
特性的<a>
元素;document.forms
,包含文档中所有的<form>
元素document.images
,包含文档中所有的<img>
元素document.links
,包含文档中所有带href 特性的<a>
元素。这些特殊集合始终都可以通过HTMLDocument
对象访问到,与HTMLCollection
对象类似,集合中的项也会随着当前文档内容的更新而更新。
write
和writeln
方法都接受一个字符串参数,即要写入到输出流中的文本。write
会原样写入,而writeln
则会在字符串的末尾添加一个换行符(\n
)。在页面被加载的过程中,可以使用这两个方法向页面中动态地加入内容。
方法open
和close
分别用于打开和关闭网页的输出流。
document.write("<strong>" + (new Date()).toString() + "</strong>");
调用document.write()
会重写页面内容,因为这样做会创建一个DOM
元素,而且可以在将来访问该元素。通过write
和writeln
输出的任何HTML
代码都将如此处理。
还可以使用write
和writeln
方法动态地包含外部资源,例如JavaScript
文件等。在包含JavaScript
文件时,必须注意不能直接包含字符串"</script>"
,因为这会导致该字符串被解释为原有脚本块的结束,它后面的代码将无法执行。应该使用转义符做处理"<\/script>"
Element
类型用于表现XML
或HTML
元素,提供了对元素标签名、子节点及特性的访问。
具有以下特征:nodeType
的值为1,nodeName
的值为元素的标签名;nodeValue
的值为null
;
所有HTML
元素都由HTMLElement
或者它的子类型来表示,HTMLElement
类型直接继承自Element
并添加了一些属性。添加的这些属性分别对应于每个HTML元素中都存在的下列标准特性。
// id,元素在文档中的唯一标识符
// title,有关元素的附加说明信息
// lang,元素内容的语言代码,很少使用。
// dir,语言的方向,值有ltr从左到右 rtl从右到做 ,很少使用
// className,与元素的class 特性对应,即为元素指定的CSS类。
<div id="myDiv" class="bd" title="Body text" lang="en" dir="ltr"></div>
getAttribute
获取属性任何元素的所有特性,可以通过DOM
元素本身的属性来访问。但自定义属性只能通过getAttribute
来获得,而使用元素.属性 = 新值
的方式设置的自定义属性是无法通过getAttribute
获得的。
有两类特殊的特性,它们虽然有对应的属性名,但属性的值与通过getAttribute
返回的值并不相同。
第一类特性就是style
,在通过getAttribute
访问时,返回的style
特性值中包含的是CSS文本,而通过属性来访问它则会返回一个对象;
第二类与众不同的特性是onclick
这样的事件处理程序,如果通过getAttribute
访问,则会返回相应代码的字符串String,而在访问onclick
属性时,则会返回一个JavaScript
函数Function,如果未在元素中指定,则返回null
。
除了上面的差别外,要想得到class
特性值,应该传入"class"
而不是"className"
,由于存在这些差别,开发人员大都只会在取得自定义特性值的情况下,才会使用getAttribute
方法。
setAttribute
获取属性:接受两个参数,要设置的特性名和值。如果该特性是存在的,则替换现有的值;不存在,则设置。通过setAttribute
方法既可以操作HTML
特性也可以操作自定义特性。
removeAttribute
删除属性:接受一个参数,即删除的属性key,不仅会清除特性的值,而且也会从元素中完全删除特性;
每个可以包含内容的元素最多只能有一个文本节点,而且必须确实有内容存在。(只有空格也算是有内容)
nodeType
的值为3
;nodeName
的值为"#text"
;nodeValue
的值为节点所包含的文本;如果这个文本节点当前存在于文档树中,那么修改文本节点的结果就会立即得到反映。另外,在修改文本节点时还要注意,此时的字符串会经过HTML
(或XML
,取决于文档类型)编码。换句话说,小于号、大于号或引号都会像下面的例子一样被转义。
Some <strong>other</strong> message
转义为
Some <strong>other</strong> message
document.createTextNode
: 创建新文本节点,接受一个参数,即要插入节点中的文本。与设置已有文本节点的值一样,作为参数的文本也将按照HTML
或XML
的格式进行编码,也属于“文档碎片”。
var textNode = document.createTextNode("Hello world!");
element.appendChild(textNode);
一般情况下,每个元素只有一个文本子节点。不过,在某些情况下也可能包含多个文本子节点,比如使用appendChild()
方法多次添加文本节点,那么这两个节点中的文本就会连起来显示,中间不会有空格。如果在一个包含两个或多个文本节点的父元素上调用normalize
方法,则会将所有文本节点合并成一个节点,结果节点的nodeValue
等于将合并前每个文本节点的nodeValue
值拼接起来的值。
DOM
操作往往是JavaScript
程序中开销最大的部分,而访问NodeList
导致的问题最多。因为NodeList
对象都是“动态的”,这就意味着每次访问NodeList
对象,都会运行一次查询。有鉴于此,最好的办法就是尽量减少DOM
操作。
指的是在页面加载时不存在,但将来的某一时刻通过修改DOM动态添加的脚本。
1、插入外部文件
function loadScript(url){
var script = document.createElement("script");
script.type = "text/javascript";
script.src = url;
document.body.appendChild(script); // 在这行代码执行之前都不会下载文件
}
loadScript("client.js"); // 方法调用时 动态添加script标签 并执行脚本
2、行内方式,也是添加script标签 ,但是脚本代码吧不是从外部引入,而是本地添加进去。所有写在标签对中的代码都算是script元素的文本节点
var script = document.createElement("script");
script.type = "text/javascript";
// 有的浏览器 不支持text属性 可以使用 script.appendChild(document.createTextNode(code))
script.text = "function sayHi(){alert('hi');}";
document.body.appendChild(script);
能够把CSS 样式包含到HTML 页面中的元素有两个。其中,<link>
元素用于包含来自外部的文件,而<style>
元素用于指定嵌入的样式。
1、外部引入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("myStyle.css");
2、内部style:这种方式会实时地向页面中添加样式,因此能够马上看到变化。
function loadStyleString(css){
var style = document.createElement("style");
style.type = "text/css";
try{
style.appendChild(document.createTextNode(css));
} catch (ex){ // 兼容IE
style.styleSheet.cssText = css;
}
var head = document.getElementsByTagName("head")[0];
head.appendChild(style);
}
loadStyleString("body{background-color:red}");
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
集合中的指定位置插入一个单元格,返回对新插入单元格的引用。理解NodeList
及其“近亲”NamedNodeMap
和HTMLCollection
,是从整体上透彻理解DOM
的关键所在。这三个集合都是“动态的”;换句话说,每当文档结构发生变化时,它们都会得到更新。因此,它们始终都会保存着最新、最准确的信息。从本质上说,所有NodeList
对象都是在访问DOM
文档时实时运行的查询。
如果想要迭代一个NodeList
,因为NodeList
是动态的,NodeList.length
也是动态的,如果在迭代的过程对这个NodeList
有添加Node
的操作,将会无限迭代下去,所以在这种场景一下,应该使用变量暂存length:var len = NodeList.length
一般来说,应该尽量减少访问NodeList
的次数。因为每次访问NodeList
,都会运行一次基于文档的查询。所以,可以考虑将从NodeList
中取得的值缓存起来。