You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<body><pid="para1">Some text here</p><buttononclick="changeColor('blue');">blue</button><buttononclick="changeColor('red');">red</button></body><script>functionchangeColor(newColor){varelem=document.getElementById("para1");elem.style.color=newColor;}</script>
<scripttype="text/javascript">
function getElements()
{varx=document.getElementsByName("myInput");alert(x.length);}</script><body><inputname="myInput"type="text"size="20"/><br/><inputname="myInput"type="text"size="20"/><br/><inputname="myInput"type="text"size="20"/><br/><br/><inputtype="button"onclick="getElements()"value="How many elements named 'myInput'?"/>
</body>
1 什么是DOM
文档对象模型 (DOM) 是HTML和XML文档的编程接口。它提供了对文档的结构化的表述,并定义了一种方式可以使从程序中对该结构进行访问,从而改变文档的结构,样式和内容。
文档对象模型 (DOM) 是对HTML文件的另一种展示,通俗地说,一个HTML 文件,我们可以用编辑器以代码的形式展示它,也可以用浏览器以页面的形式展示它,同一份文件通过不同的展示方式,就有了不一样的表现形式。而DOM 将文档解析为一个由节点和对象(包含属性和方法的对象)组成的结构集合。简言之,它会将web页面和脚本或程序语言连接起来,我们可以使用脚本或者程序语言通过DOM 来改变或者控制web页面。
2 如何访问DOM
我们可以通过JavaScript 来调用
document
和window
元素的API来操作文档或者获取文档的信息。3 Node
Node 是一个接口,有许多接口都从Node 继承方法和属性:
Document
,Element
,CharacterData (which Text, Comment, and CDATASection inherit)
,ProcessingInstruction
,DocumentFragment
,DocumentType
,Notation
,Entity
,EntityReference
。Node 有一个
nodeType
的属性表示Node 的类型,是一个整数,不同的值代表不同的节点类型。具体如下表所示:节点类型常量
Node.ELEMENT_NODE
<p>
和<div>
Node.TEXT_NODE
Element
或者Attr
中实际的文字Node.PROCESSING_INSTRUCTION_NODE
ProcessingInstruction
,例如<?xml-stylesheet ... ?>
声明Node.COMMENT_NODE
Comment
节点Node.DOCUMENT_NODE
Document
节点Node.DOCUMENT_TYPE_NODE
DocumentType
节点。例如<!DOCTYPE html>
就是用于 HTML5 的Node.DOCUMENT_FRAGMENT_NODE
DocumentFragment
节点已弃用的节点类型常量
Node.ATTRIBUTE_NODE
Node
接口将不再实现这个元素属性Node.CDATA_SECTION_NODE
CDATASection
。在DOM4 规范里被移除Node.ENTITY_REFERENCE_NODE
Node.ENTITY_NODE
<!ENTITY ...>
节点。在DOM4 规范中被移除Node.NOTATION_NODE
<!NOTATION ...>
节点。在DOM4 规范里被移除假设我们要判断一个Node 是不是一个
元素
,通过查表可知元素
的nodeType
属性值为1,代码可以这么写:在Node 类型中,比较常用的就是
element
,text
,comment
,document
,document_fragment
这几种类型。3.1 Element
Element提供了对元素标签名,子节点和特性的访问,我们常用HTML元素比如
div
,span
,a
等标签就是element
中的一种。Element有下面几条特性:(1)nodeType为1
(2)nodeName为元素标签名,tagName也是返回标签名
(3)nodeValue为null
(4)parentNode可能是Document或Element
(5)子节点可能是Element,Text,Comment,Processing_Instruction,CDATASection或EntityReference
3.2 Text
Text表示文本节点,它包含的是纯文本内容,不能包含html代码,但可以包含转义后的html代码。Text有下面的特性:
(1)nodeType为3
(2)nodeName为#text
(3)nodeValue为文本内容
(4)parentNode是一个Element
(5)没有子节点
3.3 Comment
Comment表示HTML文档中的注释,它有下面的几种特征:
(1)nodeType为8
(2)nodeName为#comment
(3)nodeValue为注释的内容
(4)parentNode可能是Document或Element
(5)没有子节点
3.4 Document
Document表示文档,在浏览器中,
document
对象是HTMLDocument的一个实例,表示整个页面,它同时也是window对象的一个属性。Document有下面的特性:(1)nodeType为9
(2)nodeName为#document
(3)nodeValue为null
(4)parentNode为null
(5)子节点可能是一个DocumentType或Element
3.5 DocumentFragment
DocumentFragment是所有节点中唯一一个没有对应标记的类型,它表示一种轻量级的文档,可能当作一个临时的仓库用来保存可能会添加到文档中的节点。DocumentFragment有下面的特性:
(1)nodeType为11
(2)nodeName为#document-fragment
(3)nodeValue为null
(4)parentNode为null
4 节点创建型API
用如其名,这类API是用来创建节点的
4.1 createElement
createElement
通过传入指定的一个标签名来创建一个元素,如果传入的标签名是一个未知的,则会创建一个自定义的标签,注意:IE8以下浏览器不支持自定义标签。语法
使用
createElement
要注意:通过createElement
创建的元素并不属于HTML文档,它只是创建出来,并未添加到HTML文档中,要调用appendChild
或insertBefore
等方法将其添加到HTML文档树中。例子:
运行结果为:
4.2 createTextNode
createTextNode
用来创建一个文本节点语法
createTextNode
接收一个参数,这个参数就是文本节点中的文本,和createElement
一样,创建后的文本节点也只是独立的一个节点,同样需要appendChild
将其添加到HTML文档树中例子:
运行结果为:
4.3 cloneNode
cloneNode
返回调用该方法的节点的一个副本语法
node
将要被克隆的节点dupNode
克隆生成的副本节点deep
(可选)是否采用深度克隆,如果为true,则该节点的所有后代节点也都会被克隆,如果为false,则只克隆该节点本身.这里有几点要注意:
(1)和
createElement
一样,cloneNode
创建的节点只是游离有HTML文档外的节点,要调用appendChild
方法才能添加到文档树中(2)如果复制的元素有
id
,则其副本同样会包含该id
,由于id
具有唯一性,所以在复制节点后必须要修改其id
(3)调用接收的
deep
参数最好传入,如果不传入该参数,不同浏览器对其默认值的处理可能不同注意
如果被复制的节点绑定了事件,则副本也会跟着绑定该事件吗?这里要分情况讨论:
(1)如果是通过addEventListener或者比如onclick进行绑定事件,则副本节点不会绑定该事件
(2)如果是内联方式绑定比如:
<div onclick="showParent()"></div>
,这样的话,副本节点同样会触发事件。例子:
运行结果为:
4.4 createDocumentFragment
DocumentFragments
是DOM节点。它们不是主DOM树的一部分。通常的用例是创建文档片段,将元素附加到文档片段,然后将文档片段附加到DOM树。在DOM树中,文档片段被其所有的子元素所代替。因为文档片段存在于内存中,并不在DOM树中,所以将子元素插入到文档片段时不会引起页面回流(reflow)(对元素位置和几何上的计算)。因此,使用文档片段
document fragments
通常会起到优化性能的作用。语法
例子:
运行结果为:
4.5 节点创建型API总结
节点创建型API主要包括
createElement
,createTextNode
,cloneNode
和createDocumentFragment
四个方法,需要注意下面几点:(1)它们创建的节点只是一个孤立的节点,要通过
appendChild
添加到文档中(2)
cloneNode
要注意如果被复制的节点是否包含子节点以及事件绑定等问题(3)使用
createDocumentFragment
来解决添加大量节点时的性能问题5 页面修改型API
前面我们提到节点创建型API,它们只是创建节点,并没有真正修改到页面内容,而是要调用·appendChild·来将其添加到文档树中。我在这里将这类会修改到页面内容归为一类。
修改页面内容的api主要包括:
appendChild
,insertBefore
,removeChild
,replaceChild
。5.1 appendChild
appendChild
我们在前面已经用到多次,就是将指定的节点添加到调用该方法的节点的子元素的末尾。语法
child节点将会作为parent节点的最后一个子节点。
appendChild
这个方法很简单,但是还有有一点需要注意:如果被添加的节点是一个页面中存在的节点,则执行后这个节点将会添加到指定位置,其原本所在的位置将移除该节点,也就是说不会同时存在两个该节点在页面上,相当于把这个节点移动到另一个地方。如果child绑定了事件,被移动时,它依然绑定着该事件。
例子:
运行结果:
5.2 insertBefore
insertBefore
用来添加一个节点到一个参照节点之前语法
parentNode
表示新节点被添加后的父节点newNode
表示要添加的节点refNode
表示参照节点,新节点会添加到这个节点之前例子:
运行结果:
关于第二个参数参照节点还有几个注意的地方:
(1)refNode是必传的,如果不传该参数会报错
(2)如果refNode是undefined或null,则insertBefore会将节点添加到子元素的末尾
5.3 removeChild
删除指定的子节点并返回
语法
deletedChild
指向被删除节点的引用,它等于node
,被删除的节点仍然存在于内存中,可以对其进行下一步操作。注意:如果被删除的节点不是其子节点,则程序将会报错。我们可以通过下面的方式来确保可以删除:
运行结果:
通过节点自己获取节点的父节点,然后将自身删除
5.4 replaceChild
replaceChild
用于使用一个节点替换另一个节点语法
newChild
是替换的节点,可以是新的节点,也可以是页面上的节点,如果是页面上的节点,则其将被转移到新的位置oldChild
是被替换的节点例子:
运行结果:
5.5 页面修改型API总结
页面修改型API主要是这四个接口,要注意几个特点:
(1)不管是新增还是替换节点,如果新增或替换的节点是原本存在页面上的,则其原来位置的节点将被移除,也就是说同一个节点不能存在于页面的多个位置
(2)节点本身绑定的事件会不会消失,会一直保留着。
6 节点查询型API
6.1 document.getElementById
这个接口很简单,根据元素id返回元素,返回值是Element类型,如果不存在该元素,则返回null
语法
使用这个接口有几点要注意:
(1)元素的Id是大小写敏感的,一定要写对元素的id
(2)HTML文档中可能存在多个id相同的元素,则返回第一个元素
(3)只从文档中进行搜索元素,如果创建了一个元素并指定id,但并没有添加到文档中,则这个元素是不会被查找到的
例子:
运行结果:
6.2 document.getElementsByTagName
返回一个包括所有给定标签名称的元素的HTML集合HTMLCollection。 整个文件结构都会被搜索,包括根节点。返回的 HTML集合是动态的, 意味着它可以自动更新自己来保持和 DOM 树的同步而不用再次调用
document.getElementsByTagName()
语法
(1)如果要对HTMLCollection集合进行循环操作,最好将其长度缓存起来,因为每次循环都会去计算长度,暂时缓存起来可以提高效率
(2)如果没有存在指定的标签,该接口返回的不是null,而是一个空的HTMLCollection
(3)
name
是一个代表元素的名称的字符串。特殊字符 "*" 代表了所有元素。例子:
这段代码中有两个按钮,一个按钮是显示HTMLCollection元素的个数,另一个按钮可以新增一个div标签到文档中。前面提到HTMLCollcetion元素是即时的表示该集合是随时变化的,也就是是文档中有几个div,它会随时进行变化,当我们新增一个div后,再访问HTMLCollection时,就会包含这个新增的div。
运行结果:
6.3 document.getElementsByName
getElementsByName
主要是通过指定的name
属性来获取元素,它返回一个即时的NodeList对象语法
使用这个接口主要要注意几点:
(1)返回对象是一个即时的NodeList,它是随时变化的
(2)在HTML元素中,并不是所有元素都有
name
属性,比如div
是没有name
属性的,但是如果强制设置div
的name
属性,它也是可以被查找到的(3)在IE中,如果
id
设置成某个值,然后传入getElementsByName
的参数值和id值一样,则这个元素是会被找到的,所以最好不好设置同样的值给id
和name
例子:
运行结果:
6.4 document.getElementsByClassName
这个API是根据元素的class返回一个即时的HTMLCollection
语法
elements
是一个实时集合,包含了找到的所有元素names
是一个字符串,表示要匹配的类名列表;类名通过空格分隔getElementsByClassName
可以在任何元素上调用,不仅仅是document
。调用这个方法的元素将作为本次查找的根元素这个接口有下面几点要注意:
(1)返回结果是一个即时的HTMLCollection,会随时根据文档结构变化
(2)IE9以下浏览器不支持
(3)如果要获取2个以上
classname
,可传入多个classname
,每个用空格相隔,例如例子:
class
为 'test' 的元素class
同时包括 'red' 和 'test' 的元素id
为'main'的元素的子节点中,获取所有class
为'test'的元素Array.prototype
的方法,调用时传递HTMLCollection 作为方法的参数。这里我们将查找到所有class
为'test'的div
元素:6.5 document.querySelector和document.querySelectorAll
这两个API很相似,通过css选择器来查找元素,注意选择器要符合CSS选择器的规则
document.querySelector
返回第一个匹配的元素,如果没有匹配的元素,则返回null
语法
注意,由于返回的是第一个匹配的元素,这个api使用的深度优先搜索来获取元素。
例子:
两个
class
都包含“test”的元素,一个在文档树的前面,但是它在第三级,另一个在文档树的后面,但它在第一级,通过querySelector
获取元素时,它通过深度优先搜索,拿到文档树前面的第三级的元素。运行结果:
返回的是所有匹配的元素,而且可以匹配多个选择符
语法
elementList
是一个静态的NodeList
类型的对象selectors
是一个由逗号连接的包含一个或多个CSS选择器的字符串selectors
参数中包含CSS伪元素,则返回一个空的elementList
例子:
返回一个文档中所有的
class
为"note"
或者"alert"
的div
元素这段代码通过
querySelectorAll
,使用id选择器和class选择器选择了两个元素,并依次输出其内容。要注意两点:(1)querySelectorAll也是通过深度优先搜索,搜索的元素顺序和选择器的顺序无关
(2)返回的是一个非即时的NodeList,也就是说结果不会随着文档树的变化而变化
兼容性问题:
querySelector
和querySelectorAll
在ie8以下的浏览器不支持。运行结果:
7 节点关系型API
在html文档中的每个节点之间的关系都可以看成是家谱关系,包含父子关系,兄弟关系等等
7.1 父关系型API
7.1.1 parentNode
每个节点都有一个parentNode属性,它表示元素的父节点。Element的父节点可能是Element,Document或DocumentFragment
7.1.2 parentElement
返回元素的父元素节点,与parentNode的区别在于,其父节点必须是一个Element,如果不是,则返回null
7.2 子关系型APPI
7.2.1 childNodes
返回一个即时的NodeList,表示元素的子节点列表,子节点可能会包含文本节点,注释节点等
7.2.2 children:
一个即时的HTMLCollection,子节点都是Element,IE9以下浏览器不支持
children
属性为只读属性,对象类型为HTMLCollection,你可以使用elementNodeReference.children[1].nodeName
来获取某个子元素的标签名称7.2.3 firstChild
只读属性返回树中节点的第一个子节点,如果节点是无子节点,则返回 null
7.2.4 lastChild
返回当前节点的最后一个子节点。如果父节点为一个元素节点,则子节点通常为一个元素节点,或一个文本节点,或一个注释节点。如果没有子节点,则返回
null
7.2.5 hasChildNodes
返回一个布尔值,表明当前节点是否包含有子节点.
7.3 兄弟关系型API
7.3.1 previousSibling
返回当前节点的前一个兄弟节点,没有则返回
null
Gecko内核的浏览器会在源代码中标签内部有空白符的地方插入一个文本结点到文档中.因此,使用诸如
Node.firstChild
和Node.previousSibling
之类的方法可能会引用到一个空白符文本节点, 而不是使用者所预期得到的节点7.3.2 previousElementSibling
previousElementSibling
返回当前元素在其父元素的子元素节点中的前一个元素节点,如果该元素已经是第一个元素节点,则返回null
,该属性是只读的。注意IE9以下浏览器不支持7.3.3 nextSibling
Node.nextSibling
是一个只读属性,返回其父节点的childNodes
列表中紧跟在其后面的节点,如果指定的节点为最后一个节点,则返回null
Gecko内核的浏览器会在源代码中标签内部有空白符的地方插入一个文本结点到文档中.因此,使用诸如
Node.firstChild
和Node.previousSibling
之类的方法可能会引用到一个空白符文本节点, 而不是使用者所预期得到的节点7.3.4 nextElementSibling
nextElementSibling
返回当前元素在其父元素的子元素节点中的后一个元素节点,如果该元素已经是最后一个元素节点,则返回null
,该属性是只读的。注意IE9以下浏览器不支持8 元素属性型API
8.1 setAttribute
设置指定元素上的一个属性值。如果属性已经存在,则更新该值; 否则将添加一个新的属性用指定的名称和值
语法
其中
name
是特性名,value
是特性值。如果元素不包含该特性,则会创建该特性并赋值。例子:
运行结果:
如果元素本身包含指定的特性名为属性,则可以世界访问属性进行赋值,比如下面两条代码是等价的:
8.2 getAttribute
getAttribute()
返回元素上一个指定的属性值。如果指定的属性不存在,则返回null
或""
(空字符串)语法
attribute
是一个包含attributeName
属性值的字符串。attributeName
是你想要获取的属性值的属性名称例子:
运行结果:
8.3 removeAttribute
removeAttribute()
从指定的元素中删除一个属性语法
attrName
是一个字符串,将要从元素中删除的属性名例子:
在运行之前
div
有个style="color:red"
的属性,在运行之后这个属性就被删除了运行结果:
9 元素样式型API
9.1 window.getComputedStyle
Window.getComputedStyle()
方法给出应用活动样式表后的元素的所有CSS属性的值,并解析这些值可能包含的任何基本计算假设某个元素并未设置高度而是通过其内容将其高度撑开,这时候要获取它的高度就要用到
getComputedStyle
语法
element
是要获取的元素,pseudoElt
指定一个伪元素进行匹配。返回的
style
是一个CSSStyleDeclaration对象。通过
style
可以访问到元素计算后的样式9.2 getBoundingClientRect
getBoundingClientRect
用来返回元素的大小以及相对于浏览器可视窗口的位置语法
clientRect
是一个DOMRect对象,包含left,top,right,bottom,它是相对于可视窗口的距离,滚动位置发生改变时,它们的值是会发生变化的。除了IE9以下浏览器,还包含元素的height和width等数据9.3 直接修改元素的样式
例子:
9.4 动态添加样式规则
例子:
10 总结
JavaScript中的API太多了,将这些API记住并熟练使用对JavaScript的学习是有很大的提高
The text was updated successfully, but these errors were encountered: