本章内容:DOM2 和 DOM3 的变化、操作样式和 DOMAPI、DOM遍历与范围
DOM1 级主要定义的是HTML 和 XML 文档的底层结构。DOM2 和 DOM3 级则在这个结构的基础上引入了更多的交互功能,也支持了更高级的XML特性。
DOM2 和 DOM3 的模块
- DOM2级核心(DOM Level 2 Core):在1级核心基础上构建,为节点添加更多的方法和属性。
- DOM2级视图(DOM Level 2 Views):为文档定义了基本样式信息不同的视图。
- DOM2级事件(DOM Level 2 Events):说明了如何使用事件与DOM文档交互。
- DOM2级样式(DOM Level 2 Style):定义了如何以变成的方式来访问和编辑css样式信息。
- DOM2级遍历和范围(DOM Level 2 Traversal and Range):引入了遍历DOM文档和选择其特定部分的新接口。
- DOM2级HTML(DOM Level 2 HTML):在1级HTML基础上后见,添加了更多属性、方法和新接口。
一、DOM变化
DOM2级和3级的目的在于扩展DOM API,满足操作文档的需求,同时提供更好的错误处理及特性检测能力。
为了确定浏览器是否支持这些DOM模块,可以使用 hasFeature() 来检测它们(这个方法在上一章提到过。)
var supportsDOM2Core = document.implementation.hasFeature('Core', '2.0')
var supportsDOM3Core = document.implementation.hasFeature('Core', '3.0')
var supportsDOM2HTML = document.implementation.hasFeature('HTML', '2.0')
var supportsDOM2Views = document.implementation.hasFeature('Views', '2.0')
var supportsDOM2XML = document.implementation.hasFeature('XML', '2.0')
1.1、针对XML 命名空间的变化
有了XML命名空间,不同XML文档的元素就可以混合在一起,共同构成格式良好的文档。HTML不支持XML命名空间,但XHTML支持XML命名空间。以下给出实例中,皆为XHTML文档格式
命名空间要使用xmlns特性来制定,并应将其包含在元素中。
Example XHTML page
Hello World
在这个例子中,所有的元素都默认被视为XHML 命名空间的元素。要明确地为XML命名空间创建前缀,可以使用xmlns 后跟冒号,再跟前缀。
EX XHTML Page
Hello World
有时候为了避免不同语言间的冲突,也需要使用命名空间来限定特性。
EX XHTML Page
Hello World
在只基于一种语言编写XML文档的情况下,命名空间实际上也没有什么用。不过,在混合使用两种语言的情况下,命名空间的用处就非常大了。
比如下面这个混合了 XHML 和 SVG 语言的文档。
Ex XHTML Page
通过设置命名空间,将
1.1.1、Node类型的变化
在 DOM2 级中, Node 类型包含下列特定命名空间的属性。
- localName: 不带命名空间前缀的节点名称
- namespaceURL:命名空间 URL 或者(在未指定的情况下是)null。
- prefix:命名空间前缀或者(在未指定的情况下是)null
当节点使用命名空间前缀时,其nodeName等于 prefix+ ":" + localName。
Ex XHTML Page
以上面这段代码为例。
- 对 来说
- localName 和 tagName 是 "html",
- namespaceURI 是 "http://www.w3.org/1999/xhtml"
- prefix 是 null
- 对
来说 - localName 是 "svg"
- tagName 是 "s:svg"
- namespaceURI 是 "http://www.w3.org/2000/svg"
- prefix 是 "s"
DOM3 级在此基础上更进一步,又引入了下列与命名空间相关的方法。
- isDefaultNa mespace(namespaceURI):在指定的 namespaceURI是当前节点的默认命名空间的情况下返回 true。
- lookupNamespaceURI(prefix):返回给定 prefix 的命名空间。
- lookupPrefix(namespaceURI):返回给定 namespaceURI的前缀。
针对前面的 代码调用 以上API
console.log(document.body.isDefaultNamespace('http://www.w3.org/1999/xhtml')) // true
var svg = document.getElementsByTagName('s:svg')[0] // 获取 svg的 引用
console.log(svg.lookupPrefix('http://www.w3.org/2000/svg')) // s
console.log(svg.lookupNamespaceURI('s')) // http://www.w3.org/2000/svg
1.1.2、Document 类型的变化
DOM2 级中的 Document 类型 包含下列与命名空间相关的方法:
- createElementNS(namespaceURI, tagName):使用给定的 tagName 创建一个属于命名空间 namespaceURI 的新元素
- createAttributeNS(namespaceURI, attributeName):使用给定的 attributeName 创建一个属于命名空间 namespaceURI 的新特性。
- getElementsByTagNameNS(namespaceURI, tagName):返回属于命名空间 namespaceURI 的tagName 元素的 NodeList
// 创建一个 新的 SVG 元素
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
// 创建一个属于 某个命名空间 的新特性。
var att = document.createAttributeNS('http://www.somewhere.com', 'radom')
// 取得所有 XHTML 元素
var eles = document.getElementsByTagNameNS('http://www.w3.org/1999/xhml', '*')
只有在文档中存在两个或多个命名空间时,这些与命名空间有关的方法才是必须的。
1.1.3、Element类型
DOM2级核心 中有关Element的变化,主要涉及操作特性。新增的方法如下。
- getAttributeNS(namespaceURI, localName):取得属于命名空间 namespaceURI 且 名为 localName 的特性
- getAttributeNodeNS(namespaceURI,localName):取得属于命名空间 namespaceURI 且名为 localName的特性节点。
- getElementsByTagNameNS(namespaceURI, tagName):返回属于命名空间 namespaceURI 的tagName 元素的 NodeList
- hasAttributeNS(namespaceURI, localName):确定当前元素是否有一个名为 localName 的特性,而且该特性的命名空间是 namespaceURI。注意:"DOM2 级核心"也增加了一个 hasAttribute() 方法,用于不考虑命名空间的情况。
- removeAttributeNS(namespaceURI, localName):删除属于命名空间 namespaceURI 且名为 localName 的特性
- setAttributeNS(namespaceURI, qualifiedName, value):将属于命名空间 namespaceURI 且名为 qualifiedName 的特性 将其值设置为 value
- setAttributeNodeNS(attNode):设置属于命名空间namespaceURI的特性节点。
除了第一个参数外,这些方法与 DOM1级中相关方法的作用相同;第一个参数始终都是一个命名空间URI
1.1.4、NamedNodeMap 类型的变化
NameNodeMap 类型也新增了下列与命名空间有关的方法。由于特性是通过 NameNodeMap 表示的,因此这些方法多少情况下只针对特性使用。
- getNamedItemNS(namespaceURI, localName):取得属于命名空间 namespaceURI 且名为 localName 的项。
- removeNamedItemNS(namespaceURI, localName):移除属于命名空间 namespaceURI 且民委 localName 的项。
- setNamedItemNS(node):添加 node,这个节点已经事先指定了 命名空间的信息。
由于一般都是通过 元素 访问特性,所以这些方法很少使用。
1.2、其他方面的变化
这些变化与 XML 命名空间无关,而是更倾向于确保 API 的可靠性及完整性。
1.2.1、DocumentType 类型的变化
DoucmentType 类型新增了 3个属性:publicId、ststemId 和 internalSubset。前两个属性表示的是文档类型声明中的两个信息段。
console.log(document.doctype.publicId) // -//W3C/DTD HTML 4.01//EN
console.log(document.doctype.systemId) // http://www.w3.org/TR/html4/strict.dtd
internalSubset 用于访问包含在文档类型中的额外定义。在HTML中极少用到,在XML中常用一些。
1.2.2、Document 类型的变化
Document类型变化中唯一于 命名空间无关的方法是 importNode(),这个方法的用途是从一个文档中取得一个节点,然后将其导入到另一个文档,使其成为这个这个文档的一部分。需要注意的是,每个节点都有一个 ownerDocument 属性,表示所属文档。
如果调 appendChild() 是传入的节点属于 不同文档(ownerDocument的值不一样),则会导致错误。在调用 importNode()时传入不同文档的节点则会返回一个新节点,这个新节点的所有权归当前文档所有。
importNode() 方法和 cloneNode() 方法非常相似,接受两个参数:要复制的节点、是否复制子节点,返回原来节点的副本。
var newNode = document.importNode(oldNode, true) // 深复制,复制子节点
document.body.appendChild(newNode)
同样这个方法在HTML中并不常用,在XML中使用较多。
“DOM2级视图” 模块添加了一个 名为 defaultView 的属性,其中保存着一个指针,指向拥有给定文档窗口(或框架)。IE不支持此属性,IE中 的等价属性时 prentWIndow(Opera也支持这个属性)。
确定文档的归属窗口
var parentWindow = document.defaultView || document.parentWindow
"DOM2级核心" 还为 docunebt.implementation 对象规定了两个新方法:
- createDocumentType(): 用于创建一个 新的 DocumentType 节点,接 受以下参数:
- 文档类型名称
- publicId
- systemId
var doctype = document.implementation.createDocumentType('html', '-//W3C/DTD HTML 4.01//EN', 'http://www.w3.org/TR/html4/strict.dtd')
由于既有文档类型不能改变,因此这个方法只在创建新文档时有用
- createDocument():用于创建一个新文档,接受三个参数:
- 针对文档元素的 namespaceURI
- 文档元素的标签名
- 文档类型
// 创建一个新的XML文档
var xmlDoc = document.implementation.createDocument('', 'root', null)
// 创建一个XHML 文档
// 这里的 doctype 引用 上面例子中 通过 createDocumentType创建的
var xhtmlDoc = document.implementation.createDocument('http://www.w3.org/1999//xhtml', 'html', doctype)
"DOM2级HTML" 模块 页为 document.implementation 新增了一个方法,createHTMLDocument(),改方法创建一个完整的 HTML 文档。接受一个参数:即新创建文档的标题(
var htmlDoc = document.implementation.createHTMLDocument('New Doc')
通过 createHTMLDocument() 创建的这个文档,是HTMLDocument类型的实例,具有该类型的所有属性和方法包括 title 和 body 属性。 这个方法存在兼容问题
1.2.3、Node类型的变化
添加了 isSupported() 方法。与 DOM1级的 hasFeature() 方法类似。isSupported() 方法用于确定当前节点具有什么能力。接受两个参数:特性名 和 特性版本号;返回一个布尔值。
if (document.body.isSupported('HTML', '2.0')) {
// todo
}
与 hasFeature() 类似,建议在 确定某个特性是否可用时,最好还是使用能力检测
DOM3级 引入了 两个辅助比较节点的方法:isSameNode() 和 isEqualNode()。这两个方法都接受一个节点参数,
- isSameNod():传入节点与引用节点相同时(两个节点引用的是同一个对象)返回 true。
- isEqualNode():传入节点与引用节点相等时(相同的类型,具有相等的属性,并且 attributes 和 childNodes 也相等)返回true
var div1 = document.createElement('div')
div.setAttribute('class', 'box')
var div2 = document.createElement('div')
dvi2.setAttribute('class', 'box')
console.log(div1.isSameNode(div1)) // true
console.log(div1.isEqualNode(div2)) // true
// 引用的不是同一个对象,不相同
console.log(div1.isSameNode(div2)) // false
1.2.4、框架的变化
DOM2级中有一个新属性:contentDocument,这个属性包含一个指针,指向表示框架内容的文档对象。IE8之前不支持 这个属性。但支持一个 contentWindow 的属性,该属性返回框架的 window 对象,而这个window 对象又有一个 document 属性。
// 访问内嵌框架的文档对象
var iframe = document.getElementById('myIframe')
var iframeDoc = iframe.contentDocument || iframe.contentWindow.document
所有浏览器都支持 contentWindow属性
二、样式
"DOM2级样式"围绕样式机制提供了一套API。可以通过 hasFeature() 检测是否支持。
var supportsDOM2CSS = document.implementation.hasFeature('CSS', '2.0')
var supportsDOM2CSS2 = document.implementation.hasFeature('CSS2', '2.0')
2.1、访问元素的样式
任何支持style 特性的 HTML 元素在 JavaScript中都有对应的 style 属性。这个 style 对象是 CSSStyleDeclaration 的实例。包含HTML的style 特性指定的所有样式信息。
css 中的 '-' 在JavaScript中要变成 驼峰式,比如:background-color = backgroundColor
var myDiv = document.getElementById('div')
// 设置背景颜色
myDive.style.backgroundColor = 'cyan'
// 改变大小
myDiv.style.width = '200px'
// 指定边框
myDiv.style.border = '1px solid black'
同时通过 style 对象也可以获取 style特性中指定的 样式
// 获取背景色
console.log(myDiv.style.backgroundColor)
2.1.1、DOM样式属性和方法
"DOM2级样式"规范还未 style 对象定义了一些属性和方法。
- cssText:能够访问到 style 特性中的 css代码
- length:应用元素的CSS属性的数量
- parentRule:表示CSS信息的CSSRule对象
- getPropertyPriority(propertyName):如果给定的属性使用了 !important 设置,则返回 'important';否则,返回空字符串
- getPropertyValue(propertyName):返回给定属性的字符串值。
- item(index):返回给定位置的CSS属性的名称。
- removeProperty(propertyName):从样式中删除给定属性
- setProperty(propertyName, value, priority):将给定属性设置为相应的值,并加上优先权标志('important'或一个空字符串)。
通过 cssText属性可以访问style 特性中的代码。并且如果通过 cssText 修改 特性,会重写整个 style 特性的值。
// 设置
myDiv.style.cssText = 'width: 24px; height: 30px'
// 获取
console.log(myDive.style.cssText)
length属性 与 item()方法配套使用,以便在迭代元素中定义的css属性,在使用length 和 item() 时,style 对象实际上就相当于一个集合,可以使用方括号语法来代替item()
for (var i = 0, len = myDiv.style.length; i < len; i++) {
console.log(myDiv.style[i]) // myDiv.style.item(i)
}
通过如上遍历可以取得所有的特性名,然后通过 getPropertyValue() 获取获取每一个特性值
var prop, value, i, len
for(i = 0, len = myDiv.length; i < len; i++) {
prop = myDiv.style.item(i)
value = myDiv.style.getPropertyValue(prop)
console.log(prop + ": " + value )
}
getPropertyValue() 返回的始终是CSS属性值的字符串表示。
使用getPropertyCSSValue()方法,返回一个对象。这个对象又两个属性:
- cssText
这个属性的值与 getPropertyValue() 返回的值相同 - cssValueType
返回一个数值常量:- 0:表示继承的值
- 1:表示基本的值
- 2:表示值列表
- 3:表示自定义的值
var i, prop, value, len
for(i = 0, len = myDiv.length; i < len; i++) {
prop = myDiv.style.item(i)
value = myDiv.style.getPropertyCSSValue(prop) // 获取 CSSValue 对象
console.log(prop + ': ' + value.cssText + '(' + value.cssValueType + ')')
}
要从元素的样式中移除某个 CSS 属性,需要使用 removePropertyValue() 方法。这个方法移除一个属性
myDiv.style.removeProperty('border')
2.1.2、计算的样式
"DOM2级样式"增强了 document.defaultView,提供了 getComputedStyle() 方法。这个方法接受两个参数:要取得计算样式的元素、一个伪元素字符串(例如 :after)如果不需要伪元素可以设置为 null。 返回一个 CSSStyleDeclaration 对象。
EX
var myDiv = document.getElementById('div')
var computedStyle = document.defaulltView.getComputedStyle(myDiv, null)
console.log(computedStyle .color) // rgb(255, 192, 203)
console.log(computedStyle .width) // 20px
console.log(computedStyle .height) // 30px
IE不支持 getComputedStyle() 方法。 在IE中,每个具有 style 属性的元素还有一个 currentStyle 属性。这个属性是CSSStyleDeclaration的实例,包含当前元素全部计算后的样式。
var computedStyle = myDiv.currentStyle
console.log(computedStyle.width) // 20px
在所有浏览器中,所有计算后的样式都是只读的;不能修改计算和样式对象中的css属性。
2.2、操作样式表
CSSStyleSheet类型表示的是样式表,是一套只读的接口,CSSStyleSheet 继承自 StyleSheet,从 StyleSheet接口继承而来的属性如下。
- disabled: 表示样式表是否被禁用的布尔值。这个属性是 可读/写的,将这个属性设置为 true,从以禁用样式表。
- href:如果样式表是通过包含的,则是样式表的URL;否则,是null
- media:当前样式表支持的所有媒体类型的集合。与所有 DOM 集合一样,这个集合也有一个length 属性和 一个 item() 方法。也可以使用方括号语法取得集合中特定的项。如果集合是空列表,表示样式表适用于所有媒体。在IE中,meida是一个反映 和