1、IE中DOM对象与原生js中DOM对象的不同
IE中的所有DOM对象都是以COM对象的形式实现,因此IE中的DOM对象与原生js对象的行为差异性较大。
2、DOM的定义
DOM将文档描述为一个由多层节点构成的结构,节点分为不同的类型,每种类的节点分别表示文档中不同的信息或标记。每个节点都有各自的特点、数据和方法。节点与节点之间存在某种关系,构成层次。页面结构则表示为一个特定节点为根节点的树形结构。
3、js共有12种节点类型,都继承自Node类型。因此所有节点类型都有共同的基本属性和方法。除了IE,都可以访问到Node类型。
4、所有节点的均有的属性,关系和操作
4.1 基本属性
4.1.1 nodeType:节点的类型
4.1.2 nodeName与nodeValue:节点名称和节点值,其值取决于属性nodeType的值
4.2 节点之间的关系
4.2.1 childNodes属性:节点的所有直接子节点
4.2.1.1 childNodes.length: 判断直接子节点的数量
4.2.1.2 childNodes[0]:访问节点的某个直接子节点
4.2.1.3 childNodes.item(0): 访问节点的某个直接子节点
4.2.2 parentNode属性:节点的直接父节点
4.2.3 firstChild属性:节点的第一个子节点
4.2.4 lastChilid属性:节点的最后一个子节点
4.2.5 previousSibling属性:紧挨节点的前一个兄弟节点
4.2.6 nextSibling属性:紧挨节点的后一个兄弟节点
4.2.7 ownerDocument属性:整个文档的文档节点,所有节点的根节点
4.2.8 hasChildNodes()方法:判断节点是否包含子节点
4.3 操作
4.3.1 appendChild方法:在childNodes列表末尾添加节点
4.3.2 insertBefore方法:在某个参照节点前添加节点,如果参照节点为null,那么insertBefore方法和appendChild方法执行相同的操作
4.3.3 replaceChild方法:用新的节点替换掉中的某个节点,被替换的节点仍然在文档中,只是文档中已经没有它的位置了
4.3.4 removeChild方法:移除某个节点
4.3.5 cloneNode方法:复制节点,
4.3.6 normalize方法:处理文档树中的文本节点
5 常见的8种节点
5.1 Element类型
5.2 Attr类型
5.3 Text类型
5.4 CDATASection类型
5.5 Comment类型
5.6 Document类型---9
5.7 DocumentType类型---10
5.8 DocumentFragment类型---11
一、基本属性
属性1:nodeType,表示节点的类型,
由于IE没有没有公开Node类型的构造函数,IE不识别12种类型的常量值,因此为了浏览器的兼容性,,尽量将nodeType属性与数字值进行比较
function f(){ var p=document.getElementById("nt"); if(p.nodeType==Node.ELEMENT_NODE||p.nodeType==1) alert("id为nt的节点的类型是元素"); }
属性2:nodeName和nodeValue属性
对于属于元素类型的节点,nodeName的值是大写标签名,nodeValue的值是null
function f(){ var p=document.getElementById("nt"); if(p.nodeType==Node.ELEMENT_NODE||p.nodeType==1) { alert("id为nt的节点的类型是元素,该节点的nodeName属性为"+p.nodeName+" 其nodeValue的值为"+p.nodeValue); //id为nt的节点的类型是元素,该节点的nodeName属性为P 其nodeValue的值为null } }
二、节点之间的关系
childNodes属性,保存一个NodeList对象,可以通过指定该对象的位置来访问节点的所有直接子节点,DOM结构的变化会自动反映到NodeList对象。可以通过中括号,或者item()方法访问,它还有一个属性length来判断直接子节点的数量
<script type="text/javascript"> function f(){ var p=document.getElementById("nt"); if(p.nodeType==Node.ELEMENT_NODE||p.nodeType==1) { alert(p.childNodes[0].nodeType+" and "+p.childNodes.item(0).nodeValue);//3 and www } } </script>
parentNode属性:指定文档中其直接父节点
previousSibling属性和nextSibling属性:分别指向节点的前一个兄弟节点和后一个兄弟节点
firstChild和lastChild属性:分别指向节点的第一个直接子节点和最后一个子节点
ownerDocument属性:指向整个文档的文档节点,文档中所有的节点不必回溯,可以直接访问文档的最顶层(object HTMLDocument)
hasChildNodes()方法:判断节点是否有子节点
三、操作节点
3.1 appendChild方法:someNode.appendChild(newNode),返回值是newNode,所有直接子元素的末尾,添加一个直接子元素,成为childNodes列表中所有元素的父元素parentNode的lastChild。
3.2 inserBefore方法:someNode.insertBefore(newNode,操作成功后,该参数成为newNode的同胞节点-previousSibling),两个参数:要插入的节点和参照的节点,返回值newNode,其中newNode是someNode的子元素。
someNode.insertBefore(newNode,null),如果第二个参数是null,则newNode插入后成为someNode的lastChild,与appendChild方法一致
3.3 replaceChild方法:someNode.replaceChild(newNode,要被替换掉的someNode的子节点),返回值是被替换掉的节点
3.4 removeChild方法:someNode.removeChild(someNode的某一个要被移除的子节点),返回值被移除的someNode的子节点
上述四种方法的操作均针对someNode的子节点
3.5 cloneNode方法:someNode.cloneNode(true/false),true是复制someNode及其整个子树,false只复制someNode,IE在复制节点时会复制节点的js属性,例如事件处理程序等,但其他浏览器不复制js属性
3.6 normalize方法:处理文档树中的文本节点,由于解析器的实现或者DOM操作的原因,可能出现文本节点不包含文本,或者接连出现两个文本的情况,当某个节点调用该方法时,就会在改节点的后代节点中查找上述两种情况,空白文本删除,两个连在一起的,合并。
-------------------------------------------------------常见的几种节点类型--1---------Element类型-----------------------------------------------
Element类型:用于表现HTML或者XML元素,提供对元素表签名、子节点、特性的访问
一、基本的一些属性值
1.nodeType:1或者Node.ELEMNET_NODE
2.nodeName:元素的表签名,HTML中是大写,XML中和源码中的实际标签一致,因此HTML中最好先利用方法toLowerCase(),将其转换大小写
3.nodeValue:null
4.parendNode:Document或者Element
5.有属性tagName:其值等于nodeName
二、HTMLElement类型的特性值
Element类型的子类型HTMLElement类型,所有的HTML元素均由HTMLElement类型或者HTMLElement的子类型表示,HTMLElement类型继承Element,并添加了一些新的属性,这些属性与元素的特性相对应
2.1 id:元素在文档中的唯一标示符
2.2 title:元素的附加说明信息,一般通过工具提示条显示
2.3 lang:元素内容的语言代码(较为常用的语言代码:en/zh/fr=英语/中文/法语)
2.4 dir:语言的方向(只有这两个取值:ltr/rtl=left-to-right/right-to-left)
2.5 className:为元素指定的css类
<!DOCTYPE html> <head> <meta charset="UTF-8"> </head> <html> <body> <p>This is a paragraph.</p> <p lang="fr" dir="rtl" id="my" title="message">Ceci est un paragrapheddddwwwwwwwwd.</p> <!--在js中lang,dir,id等是DOM对象的属性,但是在html文档中,是元素的特性,元素的特性与DOM的属性是对应的--> </body> </html>
var div=document.getElementById("my"); alert(div.id);//my alert(div.lang);//fr alert(div.title);//message alert(div.dir);//rtl alert(div.className);//""
三、操作上述特性的方法
3.1 getAttribute方法、setAttribute方法和removeAttribute方法。注意1,,不是getAttribute("className");注意2:;注意3:参数不区分大小写
3.2 :直接利用属性名操作div.id="my";//设置alert(div.id)//获取
3.3 attributes属性的getNamedItem,removeNamedItem,setNamedItem以及item方法
var id=element.attributes.getNamedItem("id").nodeValue; var id=element.attributes["id"].nodeValue; //尤其是在遍历元素的所有特性时,如果只需要返回指定的特性,利用每个特性节点的specified属性即可 var result=[]; for(var i=0;i<element.attributes.length;i++){ if(element.attributes[i].specified){ result.push(attributes[i].nodeName+"=\""+attributes[i].nodeValue+"\""); } } alert(result.join(" "));
3.4 :3.1与3.2方案的区别:
1 getAttribute("class")与div.className,
2 可以通过getAttribute("my_attribute")获取自定义的特性值与div.my_attribute==null(ie9以下例外),
3 div.style:利用属性名访问返回一个对象(object CSS2Properties)与div.getAttribute("style"):利用getAttribute方法返回css文本(background:#f36;)
4 div.onclick,返回一个函数(function onclick(event){alert('amy');})与div.getAttribute("onclick")返回代码字符串(alert('amy');)
通过js以编程的方式操作DOM时,一般用div.属性名,除非是自定义的特性值,一般不用getAttribute方法
一个小问题:dir与align有什么区别?
四、Element类型的子节点(浏览器之间的差异性)
4.1 Element类型的子节点一般通过childNodes属性,但是Element类型的子节点可以是Element类型的节点,也可以是Text类型的节点,还有可能是注释或者处理指令等,所以在获取childNodes时应该利用nodeType判定一下,例如下面的例子
<ul id="my">1 <li>2</li>3 <li>4</li>5 </ul>
var d=document.getElementById("my"); alert(d.childNodes.length);//ie返回2,火狐等其他浏览器返回5,因为火狐等会将li之间的空白认为是Text类型的节点
var d=document.getElementById("my"); for(var i=0;i<d.childNodes.length;i++){ if(d.childNodes[i].nodeType==1){ //如果是元素类型的节点执行什么操作 } }
4.2 利用getElementsByTagName方法获取所有该标签名的后代
<ul id="my"> <li>1-1 <ul> <li>2-1</li> <li>2-2</li> </ul> </li> <li>1-2</li> </ul>
var d=document.getElementById("my"); var dm=d.getElementsByTagName("li"); alert(dm.length);//4
五、创建元素document.createElement("标签名"),html不区分大小写,xml区分大小写
5.1 利用该方法创建时,已经为该元素指定了ownerDocument==HTMLDocument
5.2 ie7以及更早的版本中,利用document.createElement()方法传递的参数为新元素指定属性,避免下列问题:
1 不能设置动态创建的iframe元素的name特性var new_elemnet=document.createElement("<iframe name=\"my_frame\"></iframe>")
2 不能通过表单的reset()方法重设动态创建的input元素var new_elemnet=document.createElement("<input type=\"checkbox\">")
3 动态创建的type为reset的button元素,重设不了表单var new_elemnet=document.createElement("<button type=\"reset\"></button>")
4 动态创建的name相同的一组单选按钮之间没有关系,var new_elemnet=document.createElement("<input type=\"radio\" name=\"choice\" value=\"1\"></input>")
var new_elemnet=document.createElement("<input type=\"radio\" name=\"choice\" value=\"2\"></input>")
但是在指定属性前需要进行浏览器的检测,因为只有ie7及更早版本支持(client.browser.ie&&client.browser.ie<=7)
六、attribute属性
只有Element类型的节点有attribute属性,元素的每一个属性都是一个Attr节点
------------------------------常见的几种节点类型--2---------Attr类型----------------------------------------------------
一、基本的一些属性值
1.nodeType:2或者Node.ATTRIBUTE_NODE
2.nodeName:特性的名称
3.nodeValue:特性的值
4.parendNode:null
5.name:其值等于nodeName
6.value:其值等于nodeValue
7.specified:布尔值,用于检验特性是指定的还是默认的
8.Attr节点在html中没有子节点,在xml中子节点为Text类型或者EntityReference
9.虽然Attr也是节点,但是却不被认为是DOM文档书的一部分
二、Element类型节点的attributes属性中的每一个属性都是一个Attr节点,attributes属性是NamedNodeMap
2.1 getNamedItem(name):返回nodeName为参数name的节点
区别getAttributeNode()返回的是该特性的节点与上面的getNamedItem()方法一样
getAttribute()获取到的是该名称相对应的特性值
2.2 setNamedItem(Attr_node):返回nodeName为参数name的节点 或者setAttributeNode(Attr_node)
2.3 removeNamedItem(name):返回nodeName为参数name的节点
2.4 item(pos):返回nodeName为参数name的节点
2.5 createAttribute():创建特性节点
var my_node=document.getElementById("my"); var new_dir=document.createAttribute("dir");//常见一个特性节点 new_dir.value="rtl";//为新的特性节点设置值 my_node.attributes.setNamedItem(new_dir);//将特性值添加到某个元素节点上
my_node.setAttributeNode(new_dir);//将特性值添加到某个元素节点上 alert(my_node.attributes.getNamedItem("dir").value);//获取新增特性的值
alert(my_node.attributes.item(0).value);
alert(my_node.attributes["id"].value);
alert(my_node.attributes[1].value);
2.5 也可以利用getAttribute、setAttribute、removeAttribute方法来替代上面的方法
2.6 注意attributes属性包含了元素节点所有的属性,包括指定的默认的,大约有100多个,所以我们可以利用attributes的specified属性来返回指定的属性,另外可以利用length属性来遍历
2.6.1 element.attributes.specified
2.6.2 element.attributes.length
-------------------------------------------------------常见的几种节点类型--3---------Text类型-----------------------------------------------------
一、基本的一些属性值
1.nodeType:3或者Node.TEXT_NODE
2.nodeName:#text
3.nodeValue:所包含的文本
4.parendNode:Element类型的节点
5.data:其值等于nodeValue
6.length:节点中字符的数目
二、Text节点的操作方法
2.1 appendData(text)
2.2 deleteData(offset,count)
2.3 insertData(offset, text)
2.4 replaceData(offset,count,text)
2.5 splitText(offset):从offset位置将文本节点分为两个文本节点,
2.6 substringData(offset,count):提取从offset开始到offset+count为止的字符串,与splitData的区别是:本方法仅仅算操作字符串,对原有文本节点没有影响
三、Text类型节点的创建和添加
3.1 文本节点的创建、添加与规范化(normalize())
var new_text_node_01=document.createTextNode("hello world"); var new_text_node_02=document.createTextNode("!!!!!!"); var element_node=document.getElementById("my"); element_node.appendChild(new_text_node_01); element_node.appendChild(new_text_node_02); element_node.normalize(); alert(element_node.childNodes[0].data);
3.2 文本节点的分割(splitText())
文本的分割与文本的规范化是两个相反的过程,原本的文本节点包含从开始到指定位置的内容,新的文本节点包含剩下的内容,返回值是剩下的内容
--------------------------------------常见的几种节点类型--4--------CDATASection类型-(只针对XML文档)-------------------------------------
一、基本的一些属性值
1.nodeType:4或者Node.CDATA_SECTION_NODE
2.nodeName:#cdata_section
3.nodeValue:CDATA区域中的内容
4.parendNode:Document或者Element类型的节点
5. createCDataSection():只在XML文档中使用该方法创建CDATA区域
<div id="my"><![CDATA[this is a CADA section]]></div>四大主流的浏览器均不能解析这句话
-------------------------------------------------常见的几种节点类型--8--------Comment类型-(只针对XML文档)-------------------------------------
一、基本的一些属性值
1.nodeType:8或者Node.COMMENT_NODE
2.nodeName:#comment
3.nodeValue:或者data表示注释的内容
4.parendNode:Document或者Element类型的节点
二、一些杂乱的点
2.1 comment类型和text类型继承自一个基类,因此comment类型的节点除了没有splitText方法外,拥有Text类型节点的所有方法,包括data属性
2.2 document.createComment()可以创建注释节点,但一般都不使用,因为注释对程序影响不大
2.3 IE8及其以下版本将注释类型的节点当做了ELement类型的节点,可以使用document.getElementByTagName("!")来获取,注意利用该方法获取的还有文档类型的定义
alert(document.getElementsByTagName("!").item(0).data);
---------------------------常见的几种节点类型--9---------Document类型----------------------------------------------------
JS通过Document类型表示文档,document对象是HTMLDocument的一个实例,表示整个HTML页面,该对象也是window对象的一个属性,可以将其作为全局对象来访问
一、基本的一些属性值
1.nodeType:9或者Node.DOCUMENT_NODE
2.nodeName:#document
3.nodeValue:null
4.parendNode:null
5.documentElement:始终指向HTML页面中的<html>元素
6.childNodes:可以访问文档元素
7 body:直接指向<body>元素,所有的浏览器都支持document.documentElement和document.body属性
8 doctype:取得对<!DOCTYPE>标签的访问,注意浏览器之间的差异,但是IE将文档类型的声明,认为是Comment节点,所以document.doctype属性始终返回null,
如果定义了文档类型的声明,火狐会利用document.firstChid或者document.childNodes[0]来访问
safari、chrome和opera中,该节点并不出现在document.childNodes列表中
var html=document.documentElement;//获取对<html>的引用 alert(html.nodeName);//HTML alert(document.doctype==document.childNodes[0]);//true
9 URL:包含页面完整的URL,只可以获取,不可以设置
10 domain:只包含页面的域名,可以设置,出于安全考虑,只能给domain属性设置URL的子域的值,不能设置为URL不包含的域
注意1:如果一开始document.domain是松散的,就不能把它设置的紧绷的,例如,如果一开始是renren.com,那么就不能设置为blog.renren.com
注意2:不同子域之间无法通过JS通信,因此我们将每个页面的document.domain设置为一样的值,它们之间就可以通信了
11 referrer:保存着链接到当前页面的那个页面的URL,如果没有来源页面,referrer属性的值可能是空字符串,只可以获取,不可以设置
二、一些方法
1 getElementById:参数ID与元素的id特性严格匹配,如果页面中有多个id特性为参数ID的元素,该方法只会返回第一个匹配元素
注意:ie7以及更低版本中,该方法会返回name属性与参数ID匹配的表单元素,例如<input name="参数ID"><textarea name="参数ID"><button><select>,因此尽量避免表单元素的name特性与其他元素的id相同
2 getElementByTagName:参数是元素的标签名,返回一个HTMLCollection对象(一个“动态”集合),可以使用[]或者item()方法来访问HTMLCollection对象中的项
var imgs=document.getElementsByTagName("img"); console.log(imgs.length);//输出获取到的页面中的img元素的个数 console.log(imgs[0].src);//利用[]获取页面中第一个img元素的src属性 console.log(imgs.item(0).src);//利用item()方法获取第一个img元素的src属性
注意一:我们可以使用namedItem()方法从HTMLCollection对象中获取name属性为参数的项
<img src="my.gif" name="myImg" /><!--页面中有一个name属性为myImg的img元素-->
//首先我们使用document的getElementsByTagName方法获取到页面中的img元素 var imgs=document.getElementsByTagName("img"); //然后使用namedItem方法从imgs对象中获取到name属性与参数一致的项 var myImge=imgs.namedItem("myImg"); alert(myImge.src);
对HTMLCollection对象的操作,我们可以向[]中传入数值或者字符串形式的索引值来访问其中的项,在后台,对数值索引就会调用item(n),而对字符串索引就会调用namedItem方法
注意二:要取得文档中的所有元素,可以向getElementsByTagName方法传入"*",获取整个页面中的所有元素,按照顺序,第一项是html元素,第二项是head元素。。。依次类推,由于ie将注释也作为element,所以,会返回所有的注释节点
3 getElementsByName方法:返回name属性与参数相符的所有元素,最常见的应用就是利用该方法获取单选按钮(一组单选按钮拥有相同的name特性)
<input type="radio" value="red" name="color" id="redColor"><label for="redColor">红色</label> <input type="radio" value="green" name="color" id="greenColor"><label for="redColor">绿色</label> <input type="radio" value="blue" name="color" id="blueColor"><label for="redColor">蓝色</label>
var colorRadio=document.getElementsByName("color");
注意:这里不能再使用namedItem来取得HTMLCollection对象中的项了,因为这里获取到的元素集合,拥有相同的name特性,因此,该方法只会返回第一项
4 write(),writeln()在页面呈现的过程中直接向页面输出内容,如果在页面加载完毕后调用上述方法,那么就会重新加载页面
5 open()和close()方法:分别是打开和关闭网页输出流,如果在页面加载时使用了write或者writeln方法,就不需要使用open和close方法
三、一些特性
1 特殊的集合:
1 document.anchors:返回文档中所有带name特性的<a>元素
2 document.forms:返回文档中所有的<form>元素
3 document.images:返回文档中所有的<img>元素
4 document.links:返回文档中所有的带href特性的<a>元素
2 DOM一致性检测
由于DOM分为多个级别,也包含多个部分,因此检测浏览器实现了DOM的哪些部分十分必要
1 document.implementation.hasFeature():参数要检测的DOM功能的名称及其版本号
document.implementation.hasFeature("XML","1.0");//检测浏览器是否支持XML1.0版本的功能
4 缺陷:有时该方法返回true并不意味着实现与规范一致,因此,我们建议使用DOM一致性检测的同时,使用能力检测
---------------------------常见的几种节点类型--10---------DocumentType类型----------------------------------------------------
DocumentType类型仅火狐,safari和opera支持,所以在此简单介绍,DocumentType包含着与文档的doctype有关的所有信息,由于IE不支持,所以document.doctype的值始终为null
一、基本的一些属性值
1.nodeType:10或者Node.DOCUMENT_TYPE_NODE
2.nodeName:doctype的名称
3.nodeValue:null
4.parendNode:document
5.childNodes:不支持子节点
6 document.doctype:取得对<!DOCTYPE>标签的访问,注意浏览器之间的差异,但是IE将文档类型的声明,认为是Comment(注释)节点,所以document.doctype属性始终返回null,
二、属性----只有name是有用的,表示文档类型的名称
console.log(document.doctype.name); //HTML
--------------------------常见的几种节点类型--11---------DocumentFragment类型----------------------------------------------------
在所有节点类型中,只有DocumentFrament在文档中没有对应的标记,DOM规定文档片段是一种“轻量级”的文档,可以包含和控制节点,但不会像完整的文档那样占用额外的资源
一、基本的一些属性值
1.nodeType:11或者Node.DOCUMENT_FRAGMENT_NODE
2.nodeName:#document-fragment
3.nodeValue:null
4.parendNode:null
二、方法
1 createDocumentFrament()
虽然不能将文档片段之间添加到文档中,但是可以将它作为一个“仓库”来保存将来可能会添加到文档中的节点,首先需要创建文档片段
var fragment=document.createDocumentFragment()
2 文档片段继承了Node的所有方法,(回顾一下),appendChild,insertBefore,replaceChild,removeChild等
3 将文档中的节点添加到文档片段中,那么就会从文档中移除该节点
var fragment=document.createDocumentFragment() var my=document.getElementById("myList"); fragemnt.appendChild(my);//id为myList的节点就会从文档中移除,不再属于文档
4 将文档片段中的内容添加到文档中,实际上文档片段本身永远不会成为文档的一部分,我们只是将其内容添加到文档中(应用场景:避免逐个添加节点,导致浏览器的反复渲染新信息,利用文档片段来保存要添加的节点内容,然后将其一次性的添加到文档中)
var fragment=document.createDocumentFragment(); var ul=document.getElementById("myList"); var li=null; for(var i=0;i<3;i++){ li=document.createElement("li"); li.appendChild(document.createTextNode("item"+(i+1))); fragment.appendChild(li); //将生成的节点逐个添加到文档片段中 } ul.appendChild(fragment);//一次性将文档片段添加到文档中,文档片段中的所有节点被转移到ul后,文档片段将其内容删除
--------------------------------------------------------------------DOM扩展-------------------------------------------------------------------------------
根据W3C对DOM的要求,浏览器可以自行为其添加属性和方法,以增强其功能,这就是DOM的扩展
1 呈现模式:ie6开始区分标准模式和混杂模式,为此ie为document对象添加了compatMode属性,该属性的作用是表示浏览器处于什么模式
if(document.compatMode=="CSS1Compat"){ alert("标准模式"); }else{ alert("混杂模式"); }
另外,ie8又为document对象引入了documentMode属性,因为ie8有三种不同的呈现模式,分别是5:混杂模式(ie5);7:ie7仿真模式;8:ie8的标准模式
if(document.documentMode>7){ alert("IE8标准模式"); }else if(document.documentMode>5){ alert("IE7仿真模式"); }else{ alert("IE5混杂模式"); }
2 滚动
DOM规范没有就如何滚动页面区域这个问题作出规定,因此各种浏览器以不同的方式控制滚动,这些方法作为HTMLElement类型的扩展存在,因此可以在所有元素上使用,所有浏览器都支持的方法有scrollIntoView()
2.1 scrollIntoView():滚动浏览器窗口或者容器元素,以便在视口中看到当前元素。如果参数是true,那么窗口会尽可能滚动到自身顶部与元素顶部平齐
<p>2</p> <!--n多个p--> <p>2</p> <img src="IMG_20130302_140426.jpg.thumb.jpg" /> <p>2</p> <!--n多个p--> <p>2</p> <div onclick="f()" style="width:100px; height:100px; border:1px solid #C03;"></div>
function f(){ document.images[0].scrollIntoView(false); }
下面的几种方法只有safari和chrome浏览器实现
2.2 scrollIntoViewIfNeeded():只在当前元素在视口不可见的情况下,才滚动浏览器窗口或者容器元素,最终让当前元素可见,如果参数为true,那么会尽量让元素在视口垂直居中显示
2.3 scrollByLines(n):将元素内容滚动指定的行数高度,参数可以是正数也可以是负数
2.4 scrollByPages(n):将元素的内容滚动指定的页面的高度,将页面主体滚动n页,可以是负数
3 children属性
ie浏览器对文本节点中空白符的解释与其他的浏览器不同,它不认为空格或者换行符为一个文本节点,因此children属性只包含元素类型的子节点
<ul id="d"><li>1</li><li>2</li> </ul>
var i=document.getElementById("d");
alert(i.childNodes.length);//ie8及其以下返回2,ie9返回为3,火狐等返回3
alert(i.children.length);//ie返回都为2,火狐不支持该方法
4 ie的contains方法与火狐的compareDocumentPosition方法判断一个节点是否是另一个节点的后代
我们经常需要确定一个节点是否是另外一个节点的后代,为此ie引入了contains方法,可以让我们无须遍历DOM树就可以获知一个节点是否是另一个节点的后代
document.documentElement.contains(document.body);//true
火狐的compareDocumentPosition方法,会返回一个表示两个节点之间关系的位掩码,1:无关;2:居前;4:居后;8:包含;16:被包含,因此掩码16与ie的contains方法一致
alert(document.documentElement.compareDocumentPosition(document.body));//20,原因是居后的4+包含的16
5 操作内容
5.1 插入文本ie的innerText属性和火狐的textContent属性
innerText属性可以操作元素中包含的所有文本内容,由浅入深,将子文档树中的所有文本拼接起来
<div id="d"> <p>p<a href="#">a1</a> </p> <a href="#">a2</a> </div>
var d=document.getElementById("d"); alert(d.innerText); //pa1 //a2
使用该属性可以获取文本内容,也可以设置文本内容,使用该属性会移除先前存在的所有子节点,改变DOM子树,
var d=document.getElementById("d"); d.innerText="'hi,good morning jim&jhon!'"; alert(d.innerText);//'hi,good morning jim&jhon!'
注意:我们还可以使用该属性过滤掉html标签,方法就是
var d=document.getElementById("d"); d.innerText=d.innerText;
为了确保跨浏览器兼容,我们通过
function getText(){ return (typeof d.textContent=="string")?d.textContent:d.innerText; }
5.2 innerHTML属性
在读取信息时,innerHTML会返回当前元素的所有子节点的HTML表现,包括元素,注释以及文本节点,但是ie和opera会将标签大写返回,火狐等会以文档中指定的形式返回,包括空格和缩进
在写信息时,会创建新的DOM子树,替换当前元素的所有子节点
注意一:利用innerHTML插入的<script>元素只有ie支持其执行,但是也是有条件的,其一是指定defer特性,第二在<script>元素前面添加微软所谓的作用域元素,即前置一个作用域内元素,作用域内元素包括文本节点,或者一个隐藏的没有结束标签的元素
div.innerHTML="_<script defer></scr"+"ipt>";//下划线即为一个文本节点,但是考虑到页面显示,要移除 div.innerHTML="<div> </div><script defer></scr"+"ipt>";//div中包含一个空格,这个空格就是一个文本节点,考虑到页面显示,也需要移除 div.innerHTML="<input type=\"hidden\"><script defer></scr"+"ipt>";//由于input是隐藏的,不影响布局,因此多使用这种方法,
注意二:在通过innerHTML属性写入<style>元素时也会遇到与插入<script>元素一样的问题,如果想在所有浏览器中都成功插入<style>元素,应该如下
//针对ie,火狐,opera div.innerHTML="_<style type=\"text/css\">body{color:red;}</style>"; div.removeChild(div.firstChild);//移除文本节点,下划线 //针对safari和chrome document.getElementByTagName("head")[0].appendChild(div.firstChild); //将<style>插入到head元素中
总结:利用innerHTML向文档中插入HTML内容,都应该先对该HTML进行无害化处理,将所有的脚本节点和事件处理程序删除,这里ie8提供了window.toStaticHTML方法,由于目前只有ie8支持该方法进行无害化处理,所以我们应该先手工检查一下文本内容
5.3 内存和性能问题
使用innerHTML和innerText替换子节点可能会导致浏览器的内存问题,尤其是ie,如果被删除的子树中的某个元素设置了事件处理程序,或者具有值为js对象的属性,那么该元素在删除后,元素与事件处理程序之间的绑定仍然存在于内存中,如果这种情况频繁出现,页面的内存数量就会增加,因此正像5.2中总结的一样,在删除或者插入以前都应该手动的移除所有的事件处理程序和js对象属性
使用innerHTML操作节点的优点:使用innerHTML比使用多次DOM操作先创建节点再添加节点效率要高,因为使用innerHTML,会创建一个HTML解析器,这个解析器是在浏览器级别的代码(通常是C++)基础上运行的,因此执行效率比执行js要快的多,不可避免,使用innerHTML解析器也会带来性能损失,因此需要合理控制innerHTML的使用次数,最好是先构建字符串,然后再一次性地将字符串赋值给innerHTML
5.4 动态脚本:动态加载的脚本会在全局作用域中执行,与在全局作用域将代码字符串传递给eval是一样的
function loadScript(code){ var script=document.createElement("script"); script.type="text/javascript"; try{ script.appendChild(document.createTextNode(code)); }catch(ex){ script.text=code;//ie将<script>视为一种特殊的元素,不允许子DOM访问其子节点,因此只能使用text属性来指向script代码 }
5.5 动态样式:两种方式,第一link,OK,第二style,ie将<style>视为一种特殊的元素,不允许子DOM访问其子节点,因此只能使用styleSheet的cssText属性来指向style文本
//link function loadLink(url){ var link=document.createElement("link"); link.rel="stylesheet"; link.type="text/css"; link.href=url; var head=document.getElemntsByTagName("head")[0]; //只有添加到head才能保证在所有浏览器中的行为一致 head.appendChild(link); } //style function loadStyle(cssString){ var style=document.createElement("style"); style.type="text/css"; try{ style.appendChild(document.createTextNode(cssString)); }catch(ex){ style.styleSheet.cssText=cssString;//只针对ie
} var head=document..getElemntsByTagName("head")[0]; head.appendChild(style); }
5.6操作表格
<table>元素拥有的属性和方法
5.6.1 caption:保存着对<caption>元素的指针
5.6.2 tBodies:是一个<tbody>元素的HTMLCollection
5.6.3 tFoot:保存着对<tfoot>的指针
5.6.4 tHead:保存着<thead>的指针
5.6.5 rows:一个表格中所有的行的HTMLCollection
5.6.6 createTHead():创建一个<thead>元素,将其放到表格中,返回引用
5.6.7 createTFoot():创建<tfoot>元素,将其放到表格中,返回引用
5.6.8 createCaption():创建<caption>元素,将其放到表格中,返回引用
5.6.9 deleteTHead():删除<thead>元素
5.6.10 deleteTFoot():删除<tfoot>元素
5.6.11 deleteCaption():删除caption元素
5.6.12 deleteRow(pos):删除指定位置的行
5.6.13 insertRow(pos):向rows集合中的指定位置插入一行
<tbody>拥有的属性和方法
5.6.1 rows:保存着tbody元素中行的HTMLCollection
5.6.2 deleteRow(pos):删除指定位置的行
5.6.3 insertRow(pos):向rows集合中的指定位置插入一行,返回对新插入行的引用
5.6.4 cells:保存着tr元素中单元格的HTMLCollection
5.6.5 deleteCell(pos):删除指定位置的单元格
5.6.6 insertCell(pos):向cells集合中的指定位置插入一个单元格,返回对新插入单元格的引用
var table=document.createElement("table"); table.border=1; var tbody=document.createElement("tbody"); table.appendChild(tbody); tbody.insertRow(0);//插入第一行 tbody.rows[0].insertCell(0);//在第一行插入第一个单元格 tbody.rows[0].cells[0].appendChild(document.createTextNode("单元格1-1"));//向第一行第一列的单元格中追加文本 tbody.rows[0].insertCell(1);//插入第一行的第二列 tbody.rows[0].cells[1].appendChild(document.createTextNode("单元格1-2"));//向第一行第二列的单元格中追加文本 tbody.insertRow(1);//插入第二行 tbody.rows[1].insertCell(0);//在第二行中插入第一列 tbody.rows[1].cells[0].appendChild(document.createTextNode("单元格2-1")); tbody.rows[1].insertCell(1);//在第二行中插入第二列 tbody.rows[1].cells[1].appendChild(document.createTextNode("单元2-2")); document.body.appendChild(table);