1. 什么是DOM
文档对象模型 (DOM) 是HTML和XML文档的编程接口。它提供了对文档的结构化的表述,并定义了一种方式可以使从程序中对该结构进行访问,从而改变文档的结构,样式和内容。DOM 将文档解析为一个由节点和对象(包含属性和方法的对象)组成的结构集合。简言之,它会将web页面和脚本或程序语言连接起来。
2.DOM节点
在 HTML DOM (Document Object Model) 中 , 每一个元素都是** 节点**:
- 整个html文档就是是一个
Document
。 - 所有的HTML元素都是元素节点。
- 所有 HTML 属性都是属性节点。
- 文本插入到 HTML 元素是文本节点。
- 注释是注释节点。
3. Document 对象
- 当浏览器载入 HTML 文档, 它就会成为
document
对象。 -
document
对象是HTML文档的根节点与所有其他节点(元素节点,文本节点,属性节点, 注释节点)。 -
Document
对象使我们可以从脚本中对 HTML 页面中的所有元素进行访问。
** 提示:**Document
对象是Window
对象的一部分,可通过window.document
属性对其进行访问。
4. Document 对象属性和方法
下表是DOM对象的全部属性和方法列表,在列表下面,详细地介绍了常见的原生javascript DOM操作。
属性 / 方法 | 描述 |
---|---|
document.activeElement |
返回当前获取焦点元素 |
document.addEventListener() |
向文档添加句柄 |
document.adoptNode(node) |
从另外一个文档返回 adapded 节点到当前文档。 |
document.anchors |
返回对文档中所有 Anchor 对象的引用。 |
document.applets |
返回对文档中所有 Applet 对象的引用。 |
document.baseURI |
返回文档的绝对基础 URI |
document.body |
返回文档的body 元素 |
document.close() |
关闭用 document.open() 方法打开的输出流,并显示选定的数据。 |
document.cookie |
设置或返回与当前文档有关的所有 cookie 。 |
document.createAttribute() |
创建一个属性节点 |
document.createComment() |
createComment() 方法可创建注释节点。 |
document.createDocumentFragment() |
创建空的 DocumentFragment 对象,并返回此对象。 |
document.createElement() |
创建元素节点。 |
document.createTextNode() |
创建文本节点。 |
document.doctype |
返回与文档相关的文档类型声明 (DTD )。 |
document.documentElement |
返回文档的根节点 |
document.documentMode |
返回用于通过浏览器渲染文档的模式 |
document.documentURI |
设置或返回文档的位置 |
document.domain |
返回当前文档的域名。 |
document.domConfig |
返回normalizeDocument() 被调用时所使用的配置 |
document.embeds |
返回文档中所有嵌入的内容(embed )集合 |
document.forms |
返回对文档中所有 Form 对象引用。 |
document. getElementsByClassName() |
返回文档中所有指定类名的元素集合。 |
document.getElementById() |
返回对拥有指定 id 的第一个对象的引用。 |
document.getElementsByName() |
返回带有指定名称的对象集合。 |
document.getElementsByTagName() |
返回带有指定标签名的对象集合。 |
document.images |
返回对文档中所有Image 对象引用。 |
document.implementation |
返回处理该文档的 DOMImplementation 对象。 |
document.importNode() |
把一个节点从另一个文档复制到该文档以便应用。 |
document.inputEncoding |
返回用于文档的编码方式(在解析时)。 |
document.lastModified |
返回文档被最后修改的日期和时间。 |
document.links |
返回对文档中所有 Area 和Link 对象引用。 |
document.normalize() |
删除空文本节点,并连接相邻节点 |
document.normalizeDocument() |
删除空文本节点,并连接相邻节点的 |
document.open() |
打开一个流,以收集来自任何 document.write() 或 document.writeln() 方法的输出。 |
document.querySelector() |
返回文档中匹配指定的CSS选择器的第一元素 |
document.querySelectorAll() |
document.querySelectorAll() 是 HTML5中引入的新方法,返回文档中匹配的CSS 选择器的所有元素节点列表 |
document.readyState |
返回文档状态 (载入中……) |
document.referrer |
返回载入当前文档的文档的 URL 。 |
document.removeEventListener() |
移除文档中的事件句柄(由 addEventListener() 方法添加) |
document.renameNode() |
重命名元素或者属性节点。 |
document.scripts |
返回页面中所有脚本的集合。 |
document.strictErrorChecking |
设置或返回是否强制进行错误检查。 |
document.title |
返回当前文档的标题。 |
document.URL |
返回文档完整的URL |
document.write() |
向文档写 HTML 表达式 或 JavaScript 代码。 |
document.writeln() |
等同于write() 方法,不同的是在每个表达式之后写一个换行符。 |
5. 常见的原生javascript DOM操作
5.1 创建元素
- 创建元素节点:
document.createElement()
使用document.createElement()
可以创建新元素。这个方法只接受一个参数,即要创建元素的标签名。这个标签名在HTML
文档中不区分大小写,在XHTML
中区分大小写。
var div = document.createElement("div");
此时,新元素尚未被添加到文档树中,因此设置各种特性均不会影响浏览器的显示。要添加到文档树,可用appendChild()
、insertBefore()
、replaceChild()
。(稍后讲到)
document.body.appendChild(div);
当把元素添加到文档树中后,这个元素做的任何修改都会实时地反应到浏览器中。
- 创建文本节点 :
document.createTextNode()
使用document.createTextNode()
来创建文本节点,这个方法接受一个参数:要插入节点的文本。与设置已有文本节点的值一样,作为参数的文本将按照HTML
或XML
的格式进行编码。
document.createTextNode("121212");
可以添加多个文本节点。假如两个文本节点是相邻的同胞节点,那么两个文本节点会连起来,中间不会有空格。
5.2 节点关系
(IE9
以前不将换行和空格看做文本节点,其他浏览器会)
文本关系如下:
2
3
4
- 父节点:
parentNode
parentNode
是指定节点的父节点。一个元素节点的父节点可能是一个元素(Element
)节点,也可能是一个文档(Document
)节点,或者是个文档碎片(DocumentFragment
)节点。
每一个节点都有一个parentNode
属性。
对于下面的节点类型:Attr
,Document
,DocumentFragment
,Entity
,Notation
,其parentNode
属性返回null
。如果当前节点刚刚被建立,还没有被插入到DOM
树中,则该节点的parentNode
属性也返回null
。
var child2 = document.getElementById("div2");
var parent = child2.parentNode;
- 子节点:
childNodes
childNodes
返回包含指定节点的子节点的** 集合**,该集合为即时更新的集合(live collection
)。
即时更新就是对节点元素的任意修改都会立即反映到结果里。
var child2 = document.getElementById("div2");
var parent = child2.parentNode;
var allChilds = parent.childNodes;
console.log(allChilds.length) // IE下是3,其他浏览器是7
var nodeAdd = document.createElement("div");
var textAdd = document.createTextNode("这是添加的文本节点");
nodeAdd.appendChild(textAdd);
parent.appendChild(nodeAdd);
console.log(allChilds.length);// IE下是4,其他浏览器是8
- 兄弟节点:
nextSibling
,previousSibling
nextSibling
返回某节点的下一个兄弟节点,previousSibling
返回某节点的上一个兄弟节点,没有的话返回null
。
注意:可能因为元素换行的原因返回的是text
节点。
var child3 = document.getElementById("div3");
var next = child3.nextSibling;
var previous = child3.previousSibling;
console.log(next); // IE下返回div4,其他返回text
console.log(previous) // IE下返回div2,其他返回text
第一个或最后一个子节点:firstChild
、lastChild
firstChild
返回node
的子节点中的第一个节点的引用,没有返回null
lastChild
返回node
的子节点中的最后一个节点的引用,没有返回null
var child3 = document.getElementById("div3");
var parent = child3.parentNode;
var first = parent.firstChild; // IE是div2,其他是text
var last = parent.lastChild; // IE是div4,其他是text
5.3 节点元素关系
只算元素,不算文本节点。
以下三个方法用法和节点关系完全一样,只是这三个方法只看元素节点,不管因为空格、换行造成的文本节点或者手动加上去的文本节点。
children
: 返回所有** 元素子节点**(IE5+、ff3.5、opera3、chrome,但在IE8及以下会将注释节点看成一个元素节点)
以下两个IE9+才支持
nextElementSibling
:返回元素的下一个兄弟元素节点
previousElementSibling
: 返回元素的上一个兄弟元素节点
5.4 节点操作
-
appendChild()
appendChild()
用于向childNodes
列表的末尾添加一个节点,并且返回这个新增的节点。
如果传入到appendChild()
里的节点已经是文档的一部分了,那结果就是将节点从原来的位置转移到新位置,任何一个节点不能同时出现在文档中的多个位置。
var returnNode = someNode.appendChild(someNode.firstChild);
// 返回第一个节点
console.log(returnNode === someNode.firstChild); // false
console.log(returnNode === someNode.lastChild); // true
-
insetBefore()
insetBefore()
可以将节点插入到某个特定的位置。这个方法接受两个参数:要插入的节点和作为参照的节点。
插入节点后,被插入的节点变成参照节点的前一个同胞节点,同时被方法返回。 如果参照节点是null
,则与appendChild()
执行相同的操作。
// 插入后成为最后一个子节点
var returnNode = someNode.insetBefore(newNode, null);
console.log(returnNode === someNode.lastChild); // true
// 插入后成为第一个子节点
var returnNode = someNode.insetBefore(newNode, someNode.firstChild);
console.log(returnNode === newNode); // true
console.log(returnNode === someNode.firstChild); // true
// 插入到最后一个子节点的前面
var returnNode = someNode.insetBefore(newNode, someNode.lastChild);
console.log(returnNode === someNode.childNodes[someNode.childnodes.length - 2]) // true
- 替换节点:
replaceChild()
replaceChild()
接受两个参数:要插入的节点和要被替换的节点。被替换的节点将由这个方法返回并从文档中被移除,同时由要插入的节点占据其位置。
// 替换第一个子节点
var returnNode = someNode.replaceChild(newNode, someNode.firstChild);
使用replaceChild()
后,被替换的节点的所有关系指针都会被复制到插入的节点上面。
- 删除节点:
removeChild()
该方法移除节点,接受一个参数,即要移除的节点,同时该方法返回被移除的节点。只能是一个节点,不能是一组节点。
// 移除第一个子节点
var returnNode = someNode.removeChild(newNode, someNode.firstChild);
- 克隆节点:
cloneNode(true/false)
返回调用该方法的节点的一个副本。参数表示是否采用深度克隆,如果为true
,则该节点的所有后代节点也都会被克隆,如果为false
,则只克隆该节点本身,文本或者换行、空格这些不会复制,因为他们都是一个textNode
。
克隆一个元素节点会拷贝它所有的属性以及属性值,当然也就包括了属性上绑定的事件(比如onclick="alert(1)")
,但不会拷贝那些使用addEventListener()
方法或者node.onclick = fn
这种用JavaScript动态绑定的事件。
注意:为了防止一个文档中出现两个ID
重复的元素,使用cloneNode()方法克隆的节点在需要时应该指定另外一个与原ID
值不同的ID
var div1 = document.getElementById("div1");
var cloneHtml = div1.cloneNode(true);
document.body.appendChild(cloneHtml);
5.5 元素选择
HTML代码示例:
2
3
4
-
querySelector
返回节点子树内与之相匹配的第一个Element
节点。如果没有匹配的节点,则返回null
。 -
querySelectorAll
返回一个包含节点子树内所有与之相匹配的Element
节点列表,如果没有相匹配的,则返回一个空节点列表。
注意:由querySelector()
、querySelectorAll()
返回的节点列表不是动态实时的(非live Collection
)。这和其他DOM查询方法返回动态实时节点列表不一样。
选择器方法接受一个或多个用逗号分隔的选择器来确定需要被返回的元素。例如,要选择文档中所有CSS的类(class
)是warning
或者note
的段落(p
)元素,可以这样写:
var special = document.querySelectorAll( "p.warning, p.note" );
也可以通过ID来查询,例如:
var el = document.querySelector( "#main, #basic, #exclamation" );
执行上面的代码后,el
就包含了文档中元素的ID是main
,basic
或exclamation
的所有元素中的第一个元素。querySelector() and querySelectorAll()
里可以使用任何CSS选择器,他们都不是live Collection
:
var notLive = document.querySelectorAll("p");
console.log(notLive);
document.getElementById("div1").removeChild(document.getElementById("div2"));
console.log(notLive);
// 上面两个输出都是输出 `p#div2.one`的引用,没有因为删除了`p`标签而使`notLive`的结果发生变化。
-
document.getElementById()
方法
返回指定 ID 的元素:
document.getElementById("demo");
-
document.getElementsByTagName()
方法
返回带有指定标签名的对象的集合:
document.getElementsByTagName("P");
-
document.getElementsByName()
方法,常用于表单(数组)
var x=document.getElementsByName("x");//x为元素name属性值
alert(x.length);
-
getElementsByClassName()
方法
当在document
对象上调用此方法时,会检索整个文档,包括根元素。(IE9
以下不支持)要匹配多个class
,则className
用空格分开。
getElementsByClassName("class1 class2");
5.6 属性操作
-
setAttribute()
添加一个新属性(attribute
)到元素上,或改变元素上已经存在的属性的值。
如果指定的属性已经存在,则其值变为传递的值。如果不存在,则创建指定的属性。也可指定为null
。如果设置为null
,最好使用removeAttribute()
。
var div2 = document.getElementById("div2");
div2.setAttribute("class", "new_class");
div2.setAttribute("id", "new_id");
-
removeAttribute()
该方法用于移除元素的属性。
var div2 = document.getElementById("div2");
div2.removeAttribute("class");
-
getAttribute()
该方法返回元素上指定属性(attribute
)的值。如果指定的属性不存在,则返回null
或""
(空字符串)。
var div2 = document.getElementById("div2");
var attr = div2.getAttribute("class");
console.log(attr);
-
hasAttribute()
hasAttribute()
返回一个布尔值,指示该元素是否包含有指定的属性(attribute
)。
参考资料:
常见的原生javascript DOM操作
廖雪峰的官方网站