DOM
(一)节点层次
1.Node类型
IE中的所有DOM对象都是以COM对象的形式。
IE未公开Node类型的构造函数,直接用数字判断 node . nodeType == 1(ELEMENT_NODE)
(1)nodeName : 标签名 nodeValue : 始终为null
(2)节点关系
childNodes属性保存NodeList对象
虽然可以通过方括号语法来访问NodeList的值,而且这个对象也有length属性,但它并不是Array实例。索引和.item()访问。转数组:
function convertToArray(nodes) {
var array = null;
Try {
array = Array . prototype . slice . call(someNode . childNodes , 0);
} cache (ex) {
array = new Array(); //<=IE8
for(var i = 0, len = nodes . length; i < len; i++) {
array . push(nodes[i]);
}
}
return array;
}
跨浏览器:( 必须先写 正常浏览器 后写 ie678 )
var node = someNode.nextElementSibling || someNode.nextSibling;
//ie678
// nextElementSibling
var one.firstElementChild || one.firstChild;
ownerDocument 直接指向整个文档的文档节点,不需层层回溯到顶端。
(3)操作节点(必须在子节点上操作,否则会出错)
appendChild(one) 如果传入节点已经是文档树种一部分,可实现转移节点的目的。返回值为父节点的最后一个子节点。
insertBefore(one, two) one节点插入到two节点后面
replaceChild(one, two) one节点替换two节点
removeChild(one)
被插入和替换的节点仍然归任然还在文档中,但在文档中已经没有了自己的位置。
(4)其它方法
.childNodes.length 算回车(但在ie<9正常) (用children只算节点)
myNode.cloneNode(false) 浅复制 true 深复制 (包括子节点)
list.appendChild(one.cloneNode(true));
IE bug会复制事件处理程序,复制前最好移除事件。
normalize() 处理文档树的文档节点(删除空文本节点,合并相邻文本节点)
2.Document类型
document对象是window对象的一个属性,因此可将其作为全局对象访问。
nodeType : 9 nodeName : #document ownerDocument : null
(1)文档子节点
子节点:DocumentType Element ProcessingInstruction Comment
document.documentElement == document.firstChild == document.childNodes[0]
document.body
document.doctype <=IE8 解释为注释 返回null
IE9+ firefox 第一个子节点
Safri、chrome、opera:存在文档声明将其解析为DocumentType节点,但不作为子节点
<=IE8 、>=Safari3.1、Opera、chrome 只为第一条注释创建节点。
IE9+ 将所有注释节点加入子节点
3.Element类型
nodeType : 1 nodeName : tagName nodeValue : null parentNode : Element/document
element .tagName.toLowerCase()
(1)HTML元素 id title lang dir className
(2)取得特性
三个DOM方法: getAttribute() setAttribute() removeAttribute
element.getAttribute(“class”);
添加/得到自定义特性,特性名称不区分大小写。HTML5自定义特性加data前缀以便验证。
HTML特性: HTMLElement 5个属性。 IE会为自定义特性也创建属性。
myDiv.mySpecialAttribute (IE之外返回undefined)
style DOM方法返回css文本,属性得到的是对象。
onclick DOM方法得到相应代码字符串,属性返回相应的js函数。
上面两个属性在<=IE7时访问相同,此时
. getAttribute(“style”)返回一个对象,
. getAttribute(“onclick”)返回函数
所以操作DOM时,开发人员不使用getAttribute(), 只使用对象属性,除非获取自定义属性。
(3)设置特性
a) setAttribute()操作HTML特性和自定义特性,特性名自动转成小写。
b)div.myColor添加自定义属性,不会转成元素的特性,通过getAttribute()得到为null,自定义属性只有在IE中会被当做元素的特性。
c)<=IE7 setAttribute()设置class、style和 事件处理,没有任何效果,推荐通过属性设置特性。
d)IE6以前不支持removeAttribute() 调用此方法不仅会清除特性值,还会从元素中完全删除特性。
(4)attributes属性
Element类型是使用attributes属性的唯一一个DOM节点类型。attributes属性中包含一个NamedNodeMap,元素的每一个特性都由一个一个Attr节点表示。
element.attributes.getNamedItem(“id”).nodeValue = “otherId”
getNamedItem(name) 返回属性为name的节点
removeNamedItem(name) 移除属性为name的节点
setNamedItem(node) 给元素新加一个特性节点
item(pos) 返回pos位置的节点
遍历 element.attributes.length <=IE7会返回所有属性,包括未设置的。
for (i = 0, len = element.attributes.length; i < len; i++) {
attrName = element.attributes[i].nodeName;
attrValue = element.attributes[i].nodeValue;
if (element.attributes[i].specified) {
array.push(attrName + "=\"" + attrValue + "\"");
}
} //specified返回true表示指定过该属性节点,<=IE7正常返回。
(5)创建元素
document.createElement(“div”);
为避免<=IE7动态创建元素的问题(P269四个问题),用如下方法:
Document.createElement(“
4.Text类型
nodeType:3 nodeName : #text
nodeValue:节点所包含的文本 parentNode: element 没有子节点
appendData(text)
deleteData(offset, count) 从offset指定位置删除count个字符,无返回值。
replaceData(offset, count, text) text将从offset开始替换count个字符
insertData(offset, text) text插入到offset位置
splitText(offset) 从offset分成两个节点,返回后一部分,offset索引属于后部分
substringData(offset, count) 提取从offset到offset+count为止处的字符串,总共取count个
length 节点中字符数目
.nodeValue.length == .data.length
设置nodeValue会经过HTML编码,要注意转义。
(1)创建文本节点
document.createTextNode(“Hello world!”) 连着用appendChild()加两个文本节点,中间无空格连接。
(2)规范化文本节点
element节点加入两个子textNode, 通过element.normalize()合并为一个textNode节点。
(3)分割文本节点
splitText(offset) 一个节点变两个,该函数返回分割后半部分
5.Comment类型
(nodeType:8 nodeName:comment nodeValue:注释内容)
有除splitText()之外的所有字符串操作方法
getElementsByTagName(“!”)
6.CDATASection类型
(4 #cdata-section nodeValue : CDATA区域中的内容)
有除splitText()之外的所有字符串操作方法
7.DocumentType类型
(10 nodeName:doctype的名称 nodeValue:null p:document)P275
8.DocumentFragment类型
(11 #document-fragment nodeValue:null p:null)
继承了Node的所有方法。文档中的节点添加到文档片段中,就会从文档中移除该节点,浏览器不显示,加到文档片段中。文档片段永远不会成文文档树的一部分,相当于一个节点仓库。
循环的向页面动态添加列表项,将会导致浏览器反复渲染,为避免这个问题,使用文档片段,如下所示:
var fragment = document.createDocumentFragment();
var ul = document.getElementsByTagName("ul")[0];
var li = null;
for (var i = 0; i < 3; i++) {
li = document.createElement("li");
li.appendChild(document.createTextNode("item" + i));
fragment.appendChild(li);
//将li暂时加到fragment中,避免持续渲染页面
}
ul.appendChild(fragment);
9.Attr类型(元素的特性 2 nodeName:特性的名称 nodeValue:特性值 )
name value
specified : bolol 特性是代码指定的 还是默认的
var attr = document.createAttribute(“align”);
attr.value = “left”;
myDiv.setAttributeNode(attr);
不建议直接访问特性节点,set get remove 更为方便。
(二)DOM操作技术
1.动态脚本
//动态js不加入文档树不执行
function loadScriptString(code) {
var script = document.createElement("script");
script.type = "text/javascript";
try {
script.appendChild(document.createTextNode(code));
} catch(ex) {
script.text = code; //兼容IE
}
document.body.appendChild(script);
}
2.动态样式
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);
}
function loadStyleString(css) {
var style = document.createElement("style");
style.type = "text/css";
try {
style.appendChild(document.createTextNode(css));
}else(ex) {
style.styleSheet.cssText = css;
}
var head = document.getElementsByTagName("head")[0];
head.appendChild(style);
}
IE设置空cssText,或者重用同一个style有可能会导致浏览器崩溃。
3.操作表格 P281
4.使用NodeList
不能用变化的作为条件,element.childNodes.length 一直给element添加子节点的话进入死循环。