DOM
10.1 节点层次
文档元素是文档最外面的元素,文档中其他所有元素都包含再文档元素中,再HTML中文档元素始终是元素
10.1.1 Node类型
①节点属性
nodeName :元素的标签名
nodeValue : 元素的值始终为NULL.
②节点关系
childNodes: 其中保存着一个NodeList对象,可以通过方括号和Item()来通过位置访问这些子节点。有length属性,但它并不是Array的实例。
parentNode: 指向父节点。包含在childNodes列表中的所有节点都具有相同的父节点。
previousSibling 和nextSibling属性,可以访问同一列表中的其他节点。
firstChild lastChild 指向节点
hasChildNodes 在节点包含一个或多个子节点的情况下返回true
③操作节点
appendChild()插入在父节点的最后一个节点
insertBefore(newCode,**)someNode.firstChild)插入某个节点 *的前面
replaceChild(newNode,someNode.firstChild)
removeChild(someNode.firstChild)移除的节点
cloneNode(),用于创建调用这个方法的节点的一个完全相同的副本,参数false/true可以选择深浅复制,深复制就是复制节点和子节点树,浅复制时只复制节点本身,无任何子节点。
normalize() 处理文档树中的文本节点。
10.1.2 Document类型
①文档子节点
元素可以通过documentElement或childNodes列表或者firstChild来访问这个元素。
document对象还有一个body属性,直接指向元素。
②文档信息
document.title包含着元素中的文本----显示在浏览器窗口的标题栏或标签页上。
document.URL取得页面的URL
document.domain取得域名
③查找元素
getElementById 返回该元素,若不存在返回NULL
getElementByTagName() 返回包含零或多个元素的Nodelist,可以通过length属性取得元素数量。
nameItem() 通过元素的name特性取得集合中的项
getElementsByName() 这个方法会返回带有给定Name特性的所有元素。最常使用的情况时取得单选按钮。为了确保发送给浏览器的值正确无误,所有单选按钮必须具有相同的name特性
④特殊集合
document.achors包含文档中所有带name特性的a元素
document.forms包含文档中所有的元素
document.images包含文档中所有的元素
document.links 包含文档中所有带Href特性的元素
⑤DOM一致性检测
document.implementation规定了一个方法,即hasFeature(),这个方法接受两个参数:要检测的DOM功能的名称和版本号。如果浏览器支持给定名称和版本的功能,则该方法返回true
⑥ 文档写入
document.write()不换行 writeln()换行
document.write()在页面被呈现的过程中直接向其中输出了内容。如果在文档加载结束以后再调用document.write(),那么输出的内容将会重写整个页面。比如 window.onload
10.1.3 Element类型
① HTML元素
id title lang (元素的语言代码) dir(语言的方向,值为ltr/rtl) className 与元素的class特性相对应 即为元素指定的CSS类
② 取得特性
getAttribute() 传递给此的特姓名与实际的特姓名相同,因此想要得到class属性值,则应该传入class而不是classname
③设置属性
setAttribute() 接受两个参数,要设置的特性名和值,存在则替换,不存在则创建。
removeAttribute()彻底删除元素的特性。调用这个方法不仅会清楚特性的值,而且会从元素中完全删除特性。
④attributes属性P266
⑤创建元素
document.createElement()在新元素上设置这些特性只是给它们赋予了相应的信息,由于新元素尚未被添加到文档树中,因此设置这些特性不会影响浏览器的显示。要把新元素添加到文档树中,可以使用appendChild() insertBefore() replaceChild()方法。
还可以用另一种方式,即为这个方法传入完整的元素标签,也可以包含属性
⑥ 元素的子节点
元素可以有任意数目的子节点和后代节点,因为元素可以时其他元素的子节点。元素的childNodes属性中包含了它的所有子节点,这些子节点有可能是元素、文本节点(空格)、注释或处理指令。不同浏览器在看待这些节点方面会有显著的不同。
10.1.4 text类型
①创建文本节点
document.createTextNode()创建文本节点,接受一个参数,即要插入节点中的文本。需要用appendChild
②规范化文本节点
normalize() 如果在一个包含两个或多个文本节点的父元素上调用Normalize()方法,则会将所有文本节点合并成一个节点,结果节点的NodeValue等于将合并前的每个文本节点的nodeValue值拼接起来的值。
var element = document.createElement("div");
element.className = "message";
var textNode = document.createTextNode("Hello world!");
element.appendChild(textNode);
var anotherTextNode = document.createTextNode("Yippee");
element.appendChild(anotherTextNode);
document.body.appendChild(element);
console.log(element.childNodes.length);//2
element.normalize();
console.log(element.childNodes.length);//1
console.log(element.firstChild.nodeValue);//"Hello world!Yippee"
③分隔文本节点
spliteText(),这个方法会将一个文本节点分成两个文本节点,按照指定位置分隔。新文本节点包含剩下的文本。
var element = document.createElement("div");
element.className = "message";
var textNode = document.createTextNode("Hello world!");
element.appendChild(textNode);
document.body.appendChild(element);
var newNode = element.firstChild/splitText(5);
console.log(element.firstChild.nodeValue);
console.log(newNode.nodeValue);
console.log(element.childNodes.length);
10.1.5 Comment 类
与text类型相似,它拥有除splitText()之外的所有字符串操作方法。另外使用document.createComment()并为其传递注释文本也可以创建注释节点。
var comment = document.createComment("a comment");
10.1.6 CDATASection类型
10.1.7 DocumentType 类型
火狐 opera safari支持,谷歌不支持
10.1.8 DoucumentFragment 类型
10.1.9 Attr类型
10.2 DOM操作技术
10.2.1 动态脚本
加载外部文件
function loadScript(url){
var script = document.createElement("script");
script.type = "text/javascript";
script.src = url;
document.body.appendChild(script);
}
loadScript("index.js");
加载函数
function loadScriptString(code){
var script = document.createElement("script");
script.type = "text/javascript";
try{
script.appendChild(document.createTextNode(code));
}catch(ex){
script.text = code;
}
document.body.appendChild(script);
}
loadScriptString("function sayhi(){alert('hi';)}");
10.2.2动态样式
能够把CSS样式放入HTML中有两种方式,一种是用包含来自外部的文件,另一个种是指在页面刚加载完成后添加到页面中的。
function loadStyles(url){
var link = document.createElement("link");
link.rel = "stylesheet";
link.type = "text/css";
link.href = url;
var head = document.getElementsByTagName("head")[0];
head.appendChild(link);
}
loadStyles("style.css");
function loadStyleString(css){
var style = document.createElement("style");
style.type = "text/css";
try{
style.appendChild(document.createRexrNode(css));
}catch(ex){
style.styleSheet.cssText = css;
}
var head = document.getElementsByTagName('head')[0];
head.appendChild(style);
}
loadStyleString("body{background-color:red}");
10.2.3 操作表格P283
对元素添加的属性和方法如下:
insertRow(pos):向rows集合中指定位置插入一行,返回对新插入行的引用
对添加的属性和方法如下:
insertCell(pos):向cells集合中的指定位置插入一个单元格,返回对新插入单元格的引用。
tbody.insertRow(0);
tbody.rows[0].insertCell(0);
tbody.rows[0].cells[0].appendChild(document.createTextNode("Cell 1,1"));
tbody.rows[0].insertCell(1);
tbody.rows[0].cells[1].appendChild(document.createTextNode("Cell 2,1"));
10.2.4 使用NodeList
每当文档结构发生变化时,它们都会得到更新。下面代码会无限循环
var divs = document.getElementByTagName("div");
for (i=0;i
document.body.appendChild(div);
}
第一行会取得文档中所有
元素的HTMLCollection。这个集合时动态的,因此只要有新
元素被添加到页面中,这个元素也会被添加到该集合中。浏览器不会将创建的所有集合都保存在一个列表中,而是再下一次访问集合时再更新集合。改变
for (var i =0,len = divs.length;i
所以最好的办法就是尽量减少DOM操作
DOM扩展
11.1 选择符API
querySelector() 接收一个CSS选择符,返回与该模式匹配的第一个元素,如果没有找到则返回null
querySelectorAll() 返回的所有匹配元素而不是一个元素,返回的是一个Nodelist实例
var ems = document.getElementById("myDiv").querySelectorAll("em");
//取得某
要取得所有返回nodelist中每一个元素,可以使用Item()也可以用方括号语法
matchesSelector()方法 P288不常用
11.2 元素遍历
对于元素间的空格,IE9及之前版本不会返回文本节点。而其他所有浏览器都会返回文本节点。
整个文档是一个文档节点,
每个HTML标签是一个元素节点,
包含在HTML元素中的文本是文本节点,
每一个HTML属性是一个属性节点(属性节点是另一个层面的理解,在浏览器后台打印的时候,不存在属性节点),
注释属于注释节点。
childElementCount : 返回子元素(不包括文本节点和注释)的个数
firstElementChild : 指向第一个子元素;firstChild(返回文档节点) 的元素节点
lastElementChild:指向最后一个子元素,lastChild的元素版
previousElementSibling :指向前一个同辈元素。previousSibling元素版
nextElementSibling :指向后一个同辈元素 nextSibling的元素版
11.3 HTML5
**getElementsByClassName()**返回带有指定类的所有元素的Nodelist
classList 属性
? add() 将给定字符串添加到列表中。如果值已经存在,就不添加了
? contains(value) 表示列中中是否存在给定的值,如果存在返回true 否则返回false
? remove(value)从列表中删除给定的字符串
? toggle(value) 如果列表中已经存在给定的值,删除它。如果列表中没有给定的值,添加它。
document.activeElement属性,这个属性始终会引用DOM中当前获得了焦点的元素。元素获取焦点的办法有页面加载、用户输入(通过按TAB键)和在代码中用focus()方法。默认情况下,文档加载期间,document.activeElement中保存的是document.body原色的引用。吻搭档加载期间,document.activeElement的值是Null
**document.hasFocus()**方法 这个方法用于确定文档是否获取了焦点,返回布尔值
readyState属性有两个可能的值 Loading(正在加载文档) complete(加载完毕)
if(document.readyState =="complete");{
//执行操作
}
compatMode属性 检测页面的兼容模式是标准的还是混杂的
if (document.compatmode == 'CSS1Compat'){
//标准模式 混杂模式是BackCompat
}
head属性 document.head 否则则仍然用getElementsByTagName()
charset属性表示文档中实际使用的字符集 默认情况下是“UTF-16,但可以通过元素、响应头部或直接设置charset属性修改这个值。 document.charset = ‘UTF-8’;
defaultCharset属性表示根据默认浏览器及操作系统的设置,当前文档默认的字符集应该是什么。如果文档没有使用默认的字符集,那charset和defaultCharset属性的值可能会不一样。
通过这两个属性可以看到文档使用的字符编码的具体信息,也能对字符编码进行准确的控制。
HTML规定可以为元素添加非标准的属性,但要添加前缀data- 目的是为元素提供与渲染无关的信息,或者提供予以信息。这些属性可以随意添加,随意命名,只要以data-开头即可。添加自定义属性后,可以通过元素的dataset属性来访问自定义属性的值。div.dataset.appId可以查看和改变值
innerHTML属性 返回与调用元素所有的子节点(包括元素注释和文本节点)对应的HTML标记。在写模式下,innerHTML会根据指定的值创建新的DOM树,然后用这个DOM树完全替换调用元素原先的所有子节点。(避免多次InnerHTML操作会使得效率变低)
outerHTML属性 在读的模式下返回调用它的元素及所有子节点的HTML标签。在写模式下,根据指定HTML字符串创建新的DOM子树,然后用这个DOM子树完全替换调用元素。
insertAdjacentHTML() 插入标记,接收两个参数,插入位置和要插入的HTML文本
? beforebegin 在当前元素前插入一个紧邻的同辈元素
? afterbegin 在当前元素之下插入一个新的子元素或在第一个子元素之前再插入新的子元素
? beforeend 再当前元素之下插入一个新的子元素或在最后一个子元素之后再插入新的子元素
? afterend再当前元素之后插入一个紧邻的同辈元素
scrollIntoView()可以再所有HTML元素中使用,通过滚动浏览器窗口或某个容器元素,调用元素就可以出现再视口中。如果给这个方法传入true参数,或者不传任何参数,那么窗口滚动之后会让调用元素的顶部和视口顶部尽可能的平齐。如果false传入,则调用元素会尽可能全部出现在视口中。
11.4 专有扩展
children属性 和childNodes没有什么区别 即在元素只包含元素子节点时,这两个属性的值相同。
var childCount = element.children.length;
var firstChild = element.child[0];
contains()方法 调用contains()方法的应该时祖先节点,也就是搜索开始的节点,这个方法接收一个参数,即要检测的后代节点。返回布尔值
console.log(document.documentElement.contains(document.body))l //true
innerText() outerText()两个和InnerHTML outerHTML差别不大
scrollIntoViewIfNeeded(alignCenter): 只在当前元素在视口中不可见的情况,才滚动浏览器窗口或容器元素,最终让它可见。如果当前元素在视口中可见,那这个方法什么也不做。如果将可选的alignCenter参数设置为true,则表示尽量将元素显示在视口中部(垂直方向)
scrollByLines(lineCount) 将元素的内容滚动指定行高,LineCount可以是正值,也可以是负值
srollByPages(pageCount) 将元素的内容滚动指定的页面高度,具体高度由元素的高度决定
//将页面主题滚动5行
document.body.scrollByLines(5);
//在当前元素不可见的时候,让它进入浏览器的视口
document.images[0].scrollIntoViewIfNeeded();
//将页面主题往回滚动1页
document.body.scrollByPages(-1)
由于scrollIntoView是唯一一个所有浏览器都支持的方法,因此还是这个方法最常用。
DOM2和DOM3
12.1DOM2的变化
12.2样式
12.2.1访问元素的样式
每一个支持样式的实例都有一个style属性,这个属性是CSSStyleDeclaration的实例,包含着通过HTML的style特性指定的所有样式信息,即行内CSS代码。但不包含外部样式与嵌入样式层叠而来的样式信息。
通过style属性指定样式信息需要将短横线写法转换为驼峰写法(只有float属性例外,属于保留字,需用cssFloat访问)。 例如:
CSS属性 JavaScript属性
background-image style.backgroundImage
color style.color
display style.display
font-family style.fontFamily
float属性是JS中的保留字,因此不能用作属性名。DOM2上对应的属性名是cssFloat
通过CSS属性可以访问style特性中的CSS代码。在读取模式下,cssText会返回浏览器对style特性中CSS代码的内部表示。在写入模式下,赋给它的值会重写整个style的值,之前的信息都会丢失
myDiv.style.cssText = "width:25px;height:100px;background-color:green;";
length属性的目的是将其与item()配套使用,因为可以在迭代中定义CSS属性
for (var i=0,lem=myDiv.style.length;i
}
无论使用方括号语法还是还是item()方法,都可以取得CSS属性名(“background-color",不是”backgroundColor)然后就可以在**getProtyValue()**中使用取得的属性名进一步取得属性的值。
var prop,value,i,len;
for (i=0,len = myDiv.style.length;i
value = myDiv.style.getPropertyValue(prop);
alert(prop+":"+value);
}
要从元素的样式中移除某个CSS属性,需要用**removeProperty()**方法。使用这个方法移除一个属性,意味着将会为该属性应用默认的样式。
myDiv.style.removeProperty("border");
12.2.2操作样式表
disable:表示样式表是否被禁用的布尔值。这个属性可读可写,设置为true则可以禁用样式表
href:如果样式表是通过包含的,则是样式表的url 否则是Null
media:当前样式表支持的所有媒体类型的集合。
title:文章的标题
type:表示样式类型的字符串。对CSS而言这个字符串是"text/css";
应用于文档的所有样式表是通过document.styleSheets集合来表示的,通过集合length属性可以获知文档中样式表的个数,而通过方括号和Item()可以访问每一个样式表。
12.2.3元素大小
1.偏移量
offsetHeight: 元素在垂直方向上占用的空间大小
offsetWidth : 元素在水平方向上占用的空间大小(算边框)
offsetLeft : 元素的左外边框至包含元素的左内边框之间的像素距离
offsetTop : 元素上外边框至包含元素的上内边框之间的像素距离
要想知道某个元素在页面的偏移量,将这个元素的属性一层层象加,如此循环至根元素。
function getElementLeft(element){
var actualLeft = element.offsetLeft;
var current = element.offsetParent;
while (current !== null){
actualLeft += current.offsetLeft;
current = current.offsetParent;
}
return actualLeft;
}
2.客户区大小
元素内容及其内边距所占据的空间大小。
clientWidth:元素内容区域宽度加上左右内边距宽度 (不算边框)
clientHeight
3.滚动大小
包含滚动内容的元素大小
scrollHeight:在没有滚动条的情况下,元素内容的总高度
scrollWidth
scrollLeft
scrollTop
4.确定元素大小
提供了一个getBoundingClientRect()方法 这个方法会返回一个矩形对象,包含四个属性 left top right bottom。这些属性给出了元素在页面中相对于视口的位置。
12.3 遍历
12.3.1 NodeIterator
document.createNodeIteator() 接收以下四个参数
root 想要作为搜索起点的树中的节点
whatToShow:表示要访问哪些节点的数字代码 P328
filter 是一个NodeFilter对象,或者一个表示应该接受还是拒绝某种特定节点的函数
entityReferenceExpansion :布尔值 表示是否扩展实体引用
var div = document.getElementById("div1");
var iterator = =document.createNodeIterator(div,NodeFilter.SHOW_ELEMENT,null,false);
var node = iterator.nextNode();
while (node !==null){
alert(node.tagName);
node = iterator.nextNode();
}//遍历div中所有元素
方法:nextNode() previousNode() 向前向后一步
12.3.2 TreeWalker
方法: nextNode() previousNode() parentNode() firstChild() lastChild() nextSibling() previousSibling ()
创建 document.createTreeWalker() 接受四个参数和前一个相同
但filter可以返回的值有所不同,除了 NodeFilter.FILTER_ACCEP和NodeFilter.FILTER_SKIP(跳过相应节点前进到子树的下一个节点)
之外 还可以使用 NodeFilter.FILTER_REJECT(则会跳过相应节点和该节点的整个子树)
但其主要的强大地方在于能够在DOM上延任何方向移动,还有一个属性是currentNode修改节点
var div = document.getElementById("div1");
var walker = document.createTreeWalker(div,NodeFilter.SHOW_ELEMENT,null,false);
walker.firstChild();
walker.nextSibling();
var node = walker.firstChild();
while(node !==null){
alert(node.tagName);
node = walker.nextSibling();
}
walker.currentNode = document.body;//修改遍历中的节点
12.4 范围
12.4.1 DOM范围实现简单选择
selectNode() 选择整个节点 包括子节点
selectNodeContents()只选择节点的子节点
setStart() 两个参数,一个参照节点,一个偏移量
setEnd()
deleteContent() 删除范围所包含的内容
extractContent() 会返回范围的文档片段,利用这个返回的值,可以将范围的内容插入到文档的其他地方,原无。
cloneContengs() 创建范围对象的一个副本 然后再文档的其他地方插入该副本,原还在。
insertNode() 可以向范围选取的开始处插入一个节点,会插入到范围选取开始的位置。这种技术可以插入一些帮助提示信息,例如再打开新窗口的链接旁边插入一幅图像。
surroundContents() 这个方法接受一个参数,即环绕范围内容的节点。
var pi = document.getElementById("p1"),
helloNode = p1.firstChild.firstChild,
worldNode = p1.lastChild.
range = document.createRange();
range.selectNode(helloNode);
var span = document.createElement("span");
span.style.backgroundColor = "yellow";
range.surroundContents(span);
collapse()来折叠范围,接收一个参数,一个布尔值,表示要折叠到范围的哪一段端。参数true表示起点 false表示终点
compareBoundaryPoints() 方法来确定这些范围是否由公共的边界(起点或终点) 这个方法接收两个参数:表示比较方式的常量值和要比较的范围。
cloneRange() 复制范围。这个方法会创建调用它的范围的一个副本。新创建的范围与原来的范围包含相同的属性,而修改它的端点不会影响原来的范围。
detach() 方法可以从创建范围的文档中分离出该范围。调用后就可以放心解除对范围的引用。从而让垃圾回收机制回收其内存了。
中所有元素 alert(my.style[i]);//或者myDive.style.item(i) prop=myDiv.style[i];