JavaScript高程第十章:DOM(上)

Node类型

除了IE(该死的IE),其余全部浏览器均可以访问到Node类型,而JS中全部节点类型都继承自Node类型,所以全部节点类型都共享着相同的基本属性和方法.
每一个节点都有一个nodeType属性,能够代表节点的类型,咱们来看看有哪些类型吧javascript

  1. Node.ELEMENT_NODE(1)css

  2. Node.ATTRIBUTE_NODE(2)html

  3. Node.TEXT_NODE(3)java

  4. Node.CDATA_SECTION_NODE(4)node

  5. Node.ENTITY_REFERENCE_NODE(5)chrome

  6. Node.ENTITY_NODE(6)编程

  7. Node.PROCESSING_INSTRUCTION_NODE(7)跨域

  8. Node.COMMENT_NODE(8)数组

  9. Node.DOCUMENT_NODE(9)浏览器

  10. Node.DOCUMENT_TYPE_NODE(10)

  11. Node.DOCUMENT_FRAGMENT_NODE(11)

  12. Node.NOTATION_NODE(12)
    nodeNamenodeValue属性则彻底取决于nodeType,对于元素节点,nodeName保存的始终为标签名,而nodeValue保存的值始终为null

childNodes属性中保存着一个NodeList对象(类数组对象,并非Array的实例),NodeList是动态的,是基于DOM结构动态执行查询的结果,咱们能经过如下方式来访问子节点.

var firstChild = someNode.childNodes[0];
var secondChild = someNode.childNodes.item(1);
var count = someNode.childNodes.length;

对于NodeList对象,咱们还能够转换为数组,以下

var arrayOfNodes = Array.prototype.slice.call(someNode.childNodes,0);

值得注意,该段代码在IE8及更早版本前是报错的,这是由于IE8及更早版本将NodeList实现为一个COM对象,而咱们不能像使用JScript对象那样使用该对象,因此上述代码会致使错误.如下是对于兼容性的解决方法.

function convertToArray(nodes){
  var array = null;
  try{
    array = Array.prototype.slice.call(nodes,0);//非IE
  }catch(ex){
    array = new Array();
    for(var i = 0,len = nodes.length;i < len;i++){
      array.push(node[i]);
    }
  }
  return array;
}

每一个节点还有parentNode属性,该属性指向文档树中的父节点.包含在childNodes列表中的全部节点都有相同的父节点,而childNodes列表中的每一个节点之间为同胞节点,能够经过previousSiblingnextSibling属性访问.若是列表只有一个节点,则该节点上述两个属性为null.
父节点与其第一个和最后一个子节点之间也存在特殊关系.父节点存在属性firstChildlastChild分别指向它们.其中firstChildchildNodes[0]相等,而x.lastChildx.childNodes[x.childNodes.length-1]相等.

节点中hasChildNodes()方法也是一个有用的方法,在包含节点状况下返回true,不然返回false.

全部节点最后一个属性都为ownerDocument,它指向表示整个文档的文档节点,即#document,可使咱们直接到达顶层.

操做节点

注意:关系指针都是只读的,因此DOM提供了一些函数供咱们操做节点.
如下介绍了四种操做方法,都须要先取得父节点,可是须要明白不是全部类型的节点都有/支持子节点.

插入节点

appendChild(node) //向childNodes列表末尾添加一个节点,并在添加后,关系指针会相应更新.

值得注意的是appendChild()添加的节点若是已是文档的一部分,那么至关于转移节点.

insertBefore(node,null) //参数一为插入节点,第二个参数则为参照节点,设为null则效果与appendChild同样,存在参照节点则插入节点变成参照节点前一个同胞节点(previousSibling)

移除/替换节点

removeChild(oldNode) //移除并不是替换节点,返回值为oldNode
replaceChild(newNode,oldNode) //oldNode替换为newNode,oldNode虽然技术上仍然存在,可是文档中没有了它的位置

其余方法

这里有两个方法是全部类型节点都有的,它们就是cloneNode(boolean)normalize(),咱们重点介绍cloneNode()

cloneNode(boolean) //传入一个布尔值,该值决定执行深复制(节点及整个节点树)仍是浅复制(仅复制自己)

注意点一:深复制IE9以前版本不会为空白符建立节点,因此深复制时childNodes长度会有所不一样.
注意点二:cloneNode()方法只复制特性和子节点(指定状况下),不会复制JS属性如事件处理程序等等(除开IE,存在复制事件处理程序的bug),因此复制前最好先移除事件处理程序.

Element类型

除了Document类型,咱们Web编程中最经常使用的类型就是Element类型啦.
Element 类型用于表现XML或HTML元素,提供了对元素标签名,子节点,特性的访问

特征

  • nodeType值为1

  • nodeName为元素标签名

  • nodeValue为null

  • parentNode多是Document或Element

  • 子节点多是Element,Text,Comment,ProcessingInstruction,CDATASection,EntityReference

其中nodeName和tagName属性返回相同的值,推荐使用tagName,则表义更清晰,值得注意的是返回值大小写的问题,因为HTML中为答谢,而XML/XHTML则会与源代码保持一致,因此比较时要统一大小写形式.
<!-- more -->

HTML元素

HTML元素都由HTMLElement类型表示,不直接经过该类型,也是经过它的子类型表示.HTMLElement类型继承自Element而且添加了一些属性以下:

  • id 元素在文档中的惟一标识符

  • title 元素的附加说明信息,通常为工具提示条显示

  • lang 元素内容的语言代码,不多使用

  • dir 语言方向,ltr为从左到右,rtl则相反

  • className 与元素class的特性对应,没有设置为class则是由于class为ECMAScript的保留字

注意以上属性的修改并非全部都会在页面中直观的表现出来,id和lang修改对用户来讲是不可见的(假设没有css样式),对title的修改则只会在鼠标移动到元素上时才会显示出来(工具提示条),dir的修改则会在属性重写的那一刻马上影响页面中的文本,对className的修改则与是否关联了不一样的CSS样式有关.

特性

HTML元素每一个元素都有一个或多个特性,操做特性的DOM方法以下有三个:

  • getAttribute()

  • setAttribute()

  • removeAttribute()
    这三个方法能够针对任何特性使用,包括自定义特性.

可是只有公认的特性才会添加到DOM元素属性上,自定义的特性一般是不存在的(undefined),固然这里又要注意咱们的"好朋友"IE啦,它会为自定义特性建立属性.

特殊特性

主要针对getAttribute()方法讲述一下特殊状况.

有两类特殊特性,有对应的属性名,但值与getAttribute()返回的值并不相同

  • style,经过getAttribute()访问会返回CSS文本,而经过属性访问返回一个对象

  • onclick这样的事件处理程序,经过getAttribute()访问会返回相应代码的字符串.而属性访问时,则会返回一个JavaScript函数(未指定则为null)

故一般只有取得自定义特性值的状况下,才会使用getAttribute()方法.

注意!:咱们的"老朋友"IE7及之前版本中,getAttribute()方法访问上述两个特殊特性时,返回的值与属性的值相同.即getAttribute("style")返回一个对象,getAttribute("onclick")返回一个函数.

设置特性

这里主要讲解下setAttribute()方法,这和getAttribute()相对应.这个方法接受两个参数,要设置的特性名和值,若是特性存在则将值进行替换;不存在则建立并设置相应的值.
值得注意的是,设置特性名会转换为小写.并且直接给DOM元素添加一个自定义的属性并不会让这个属性成为元素的特性.

div.mycolor="red";
div.getAttribute("mycolor"); //这里返回null(IE除外)

移除特性

removeAttribute()方法用于完全删除元素特性,调用该方法会清除特性的值并彻底删除特性.
注意!:IE6及之前版本不支持该方法.

attributes属性

Element类型是使用attributes属性的惟一一个DOM节点类型.在该属性中包含一个NamedNodeMap,与NodeList相似,也是"动态"集合.元素每个特性都由一个Attr节点表示,每一个节点都保存在NamedNodeMap对象中.相关方法以下:

  • getNamedItem(name)返回nodeName属性等于name的节点

  • removeNamedItem(name)从列表移除nodeName等于name的节点

  • setNamedItem(node)向列表添加节点,以节点的nodeName属性为索引

  • item(pos)返回处于数字pos位置处的节点

在该属性中有一系列的节点,每一个节点的nodeName就是特性的名称,nodeValue就是特性的值.要取得元素的id特性,可使用attributes.getNamedItem("id").nodeValue
等同于attributes["id"].nodeValue

调用removeNamedItem()与在元素上调用removeAttribute()效果相同.

setNamedItem()是一个很不经常使用的方法,该方法能够为元素添加一个新特性,此外须要为它传入一个特性节点.

注意!:IE7及更早版本会返回HTML元素中全部可能的特性,包括没指定的特性.
针对低版本改进:每一个特性节点都有一个名为specified的属性,若是为true则意味着要么HTML中指定了相应特性,要么经过setAttribute()设置了该特性,在IE中未设置过的特性都为false,其余浏览器则不会为这类特性生成对应特性节点.

建立元素

document.createElement()方法就可建立新元素.
该方法接受一个参数,就是元素标签名,这个标签名在HTML下不区分大小写,XML中则会区分大小写.

在建立新元素的同时,新元素也设置了ownerDocument属性,此时,还能够操做元素特性,为它添加更多的子节点.
在设置完特性后,因为未添加到文档树,因此一切特性都不会影响浏览器的显示.咱们能够经过以前讲到的appendChild(),insertBefore(),replaceChild()方法来进行相应的操做.
一旦添加到文档树,则浏览器会马上呈现该元素.此后咱们的修改都会反应到浏览器中.
注意!(常不考虑):在IE中咱们能够经过另外一种方式进行建立

document.createElement("<div id=\"myNewDiv\" class=\"box\"></div>");

这个方式能够避开IE7及更早版本中动态建立元素的某些问题.(不能设置动态建立的iframe元素的name特性;不能经过表单的reset()方法重设动态建立的input元素;动态建立的type特性值为"reset"的button元素重设不了表单;动态建立的一批name相同的单选按钮彼此毫无关系)

元素子节点
除了IE,其余浏览器解析代码时会解析空白符为文本节点.咱们能够经过nodeType属性的检查来过滤掉它们.

Document 类型

在JavaScript中Document类型表示文档,咱们经常使用的document对象是HTMLDocument(继承自Document类型)的一个实例,表示整个HTML页面;document对象仍是window对象的一个属性,所以能够将其做为全局对象来访问.

特征

  • nodeType值为9

  • nodeName为"#document"

  • nodeValue为null

  • parentNode为null

  • ownerDocument为null

  • 子节点多是一个DocumentType(最多一个),Element(最多一个),ProcessingInstruction或Comment

Document类型能够表示HTML页面或者其余基于XML的文档,不过最多见的应用仍是做为HTMLDocument实例的document对象.经过该对象,咱们能够获取页面有关信息,操做页面的外观,以及其底层结构.
<!-- more -->

文档子节点

虽然DOM标准规定Document节点的子节点能够是DocumentType,Element,ProcessingInstruction或Comment,可是还有两个内置的访问其子节点的快捷方式.
一:documentElement属性-始终指向HTML页面中的<html>元素
二:childNodes列表
而且以下代码所示

//html部分
//<html>
// <body></body>
//</html>

var html = document.documentElement;
console.log(html === document.childNodes[0]); //true
console.log(html === document.firstChild);    //true

可见documentElement,firstChild,childNodes[0]指向同一个元素<html>

而且做为HTMLDocument的实例,还有一个body属性,直接指向<body>元素.

全部浏览器都支持document.documentElementdocument.body属性

DocumentType节点(不重要)

<!DOCTYPE>节点能够经过document.doctype属性获取并访问它的信息.
如下是各浏览器支持差异:

  • IE8及以前:存在文档类型声明,会错误解释为一个注释并把它看成Comment节点;而document.doctype 值始终为null

  • IE9+及firefox:若是存在文档类型声明,则会将其做为文档第一个子节点;document.doctype是一个DocumentType节点,也能够经过document.firstChild或document.childNodes[0]访问.

  • Safari,Chrome和Opera:若是存在文档类型声明,则会将其解析,但不做为文档子节点,document.doctype是一个DocumentType节点,但该节点不存在于document.childNodes中.

Comment(不重要)

<!-- 注释1 -->
<html>
  <body>
  </body>
</html>
<!-- 注释2 -->

对于上述注释也在不一样浏览器中存在不一样.

  • IE8及以前,Safari3.1及更高,Opera和chrome:只为第一条注释建立节点,部位第二条注释建立节点.

  • IE9+:将第一条注释建立为document.childNodes中的一个注释节点,也将第二条注释建立为document.childNodes中的注释子节点

  • Safari3.1以前,firefox:彻底忽略

以上的不一致性致使了不管是注释仍是DocumentType节点对于咱们来讲用处十分有限.

文档信息

document对象有属性提供了document对象所表现的网页的一些信息.

  • title:包含在<title>元素中的文本(浏览器窗口的标题栏或标签页上),可是修改该值不会改变<title>元素.

  • URL:包含页面完整的URL

  • domain:包含页面的域名

  • referrer:保存连接到当前页面的那个页面的URL,如无来源页面则为空字符串.
    注意!:这些信息都存在于HTTP头部,只不过咱们能经过该属性在JS中访问它们.并且咱们只能在遵照规则(不能将这个属性设置为URL中不包含的域,不能将域缩紧如将wrox.com设置为p2p.wrox.com同样(IE8及以后))的状况下设置domain属性.

其中domain属性仍是越过跨域安全限制的好办法.

查找元素

主要用到document对象如下方法.

getElementById("id") //接受一个参数,若是找到相应元素则返回该元素,不存在则返回null

//注意!:IE8及较低版本不区分ID大小写/若是存在多个ID则只返回第一次出现的/IE7及较低版本中name值与ID匹配的表单元素会被返回

getElementsByTagName("img") //接受一个参数,为要取得元素的标签名,返回一个NodeList(包含零或多个元素).在HTML文档中,这个方法返回一个HTMLCollection对象,该对象与NodeList很是相似

getElementsByName("name") //只有HTMLDocument类型才有的方法.和上述两个方法类似,也就不解释传入参数之类的啦

HTMLCollection对象

元素数量能够经过length得到,并且咱们能够经过.item()和方括号语法[0]/["name特性"]来访问元素.namedItem()方法则能够经过name特性取得其中的元素.

特殊集合

除了属性和方法,document对象还有一些特殊集合.这些集合都是HTMLCollection对象,为访问文档经常使用部分提供了快捷方式,以下:

  • document.anchors 包含文档中全部带name特性的<a>元素

  • document.applets 包含文档中全部的<applet>元素(已再也不推荐使用)

  • document.forms 包含文档中全部<form>元素

  • document.images 包含文档中全部<img>元素

  • document.links 包含文档中全部带href特性的<a>元素
    该集合始终能够经过HTMLDocument对象访问到.并且是动态的随着当前文档内容的更新而更新.

DOM一致性(分级)

document.implementation属性就是用在检测浏览器实现了DOM的哪些部分.
document.implementation.hasFeature()方法接受两个参数,要检测的DOM功能名称和版本号,若是浏览器支持则返回true.可是这并不表明着实现与规范一致

文档写入

document对象有一个存在好久的功能,将输出流写入到网页中的能力.这关乎到下列4个方法.

  • write()

  • writeln()
    上面两个方法都是接受一个字符串参数,writeln()额外在字符串写入后再写入一个换行符

注意!:若是要用于写入<script></script>则要对</script>进行转义=></script>,防止script标签被提早闭合致使没法执行;若是在文档接在结束后再调用则会致使整个页面重写.

  • open()

  • close()上述两个方法用于打开和关闭网页的输出流,若是在页面加载期间使用write()和writeln()则不须要用到这两个方法(严格型的XHTML文档不支持文档写入)

相关文章
相关标签/搜索