《JavaScript DOM 编程艺术 》 《JavaScript 高级程序设计》
平稳退化和渐进增强
在 JavaScript DOM 编程艺术一书中,个人认为,最核心的思想是作者提到的平稳退化和渐进增强。
所谓的平稳退化,就是让JS代码适应所有的用户,这是一个基础,不管用户处于什么环境,都要为用户提供最基本的可访问性。
而渐进增强则是为高级用户提供更好的体验效果,利用JS去包装原始的HTML数据,但前提是JS只是一个行为层,必须与结构层分离。
也就是说在平稳退化的基础上渐进增强,而渐进增强的结果一般都是符合平稳退化的。
DOM
JavaScript 主要由3部分组成,也就是 ECMAScript,DOM,BOM。
作为 JavaScript 的重要组成部分,DOM 的全称是 Document Object Model,即是文档对象模型。用类似于家谱的树形结构来表示 DOM 再适合不过了,而组成这个 DOM Tree 的就是节点。
节点——Node 类型
nodeType 属性
DOM 中定义了12中 Node 类型,其中主要有3种节点:元素节点、文本节点、文档节点。
元素节点的 nodeType 属性值为 Node.ELEMENT_NODE 或 1。
文本节点的 nodeType 属性值为 Node.TEXT_NODE 或 3。
文档节点的 nodeType 属性值为 Node.DOCUMENT_NODE 或 9。
注:为了跨浏览器,一般使用数值表示 nodeType 属性。
nodeName 属性和 nodeValue 属性
childNodes 属性
关于 NodeList 对象
function convert2Array(nodes){
var array = null;
try{
//针对非IE浏览器
array = Array.prototype.slice.call(nodes, 0);
}
//IE8-浏览器会捕获错误
catch(e){
array = new Array();
for(var i = 0, len = nodes.length ; i < len ; i ++){
array.push(nodes[i]);
}
}
return array;
}
parentNode 属性、previousSibling 属性、nextSibling 属性、firstChild 属性、lastChild 属性 和 hasChildNodes() 方法
appendChild() 方法、insertBefore() 方法、replaceChild() 方法 和 removeChild() 方法
/*
原有的 html 结构:
<div id="a">
<div id="b"></div>
</div>
*/
var a = document.getElementById("a");
//若已经创造了新的节点 c
var newNode = a.appendChild(c);
alert(newNode == c); //true
/*
此时 html 结构为
<div id="a">
<div id="b"></div>
<div id="c"></div>
</div>
*/
//若新插入的节点已存在,appendChild 则会改变原来的位置为当前位置
var newNode = a.insertBefore(d,b);
alert(newNode == d); //true
/*
此时 html 结构为
<div id="a">
<div id="d"></div>
<div id="b"></div>
<div id="c"></div>
</div>
*/
var newNode = a.replace(e,d);
alert(newNode == e); //tue
/*
此时 html 结构为
<div id="a">
<div id="e"></div>
<div id="b"></div>
<div id="c"></div>
</div>
*/
var removeNode = a.removeChild(e);
alert(removeNode == e);//true
/*
此时 html 结构为
<div id="a">
<div id="b"></div>
<div id="c"></div>
</div>
*/
自定义 insertAfter() 方法
DOM 中没有提供 insertAfter() 方法,但我们可以自己定义:function insertAfter(newNode, targetNode){
var parent = targetNode.parent;
if(parent.lastChild == targetNode){
parent.appendChild(newNode);
}
else{
parent.insertBefore(newNode, targetNode.previousSibling);
}
}
文档节点——Document 类型
document 对象
查找元素:
getElementById() 方法:
注:按照平稳退化渐进增强的原则,使用前做出判断,如
if(!document.getElementById){
return false;
}
var link = document.getElementById("a");
getElementsByTagName
var links = document.getElementsByTagName("a");
for(var i = 0 ; i < links.length ; i ++){
alert(links[i].title);
}
getElementsByClassName
HTML5 DOM 中新增的一个方法,按照元素的 class 值返回一个 HTMLCollection 对象,可查找带有多个类名的元素,且类名顺序不会有影响
var links = document.getElementsByClassName("link item");
alert(links.length);
元素节点——Element 类型
属性操作
getAttribute
if(!document.getElementById){
return false;
}
var link = document.getElementById("item");
alert(link.getAttribute("src"));
link.getAttribute("src") 相当于 link.src,也就是直接采用 DOM 对象直接访问。
setAttribute
var links = document.getElementsByTagName("a");
for(var i = 0 ; i < links.length ; i ++){
links[i].setAttribute("title","title"+i);
}
links[i].setAttibute("title","title"+i) 相当于 links[i].title = "title" + i;
removeAttribute
移除属性的值
var link = document.getElementById("item");
link.removeAttribute("title");
注:IE6- 不支持
创建元素——document.ceateElement()
if(client.browser.ie && client.browser.ie <= 7){
var iframe = document.createElement("<iframe name=\"myframe\"></iframe>");
var input = document.createElement("<input type=\"checkbox\" />");
var button = document.createElement("<button type=\"reset\"></button>");
var radio1 = document.createElement("<input type=\"radio\" name=\"choice\" value=\"1\" />");
var radio2 = document.createElement("<input type=\"radio\" name=\"choice\" value=\"2\" />");
}
注:其他浏览器不支持此写法,所以要检测浏览器。
文本节点——Text 类型
创建文本节点 document.createTextNode()
var p = document.getElementById("text");
var txt1 = document.createTextNode("hello ");
var txt2 = document.createTextNode("word!");
p.appendChild(txt1);
p.appendChild(txt2);
alert(p.childNodes.length); //2
p.normalize();
alert(p.childNodes.length); //1
文档片段——DocumentFragment 类型
var fragment = document.createDocumentFragment();
var ul = document.getElementById("list");
var li = null;
for(var i = 0 ; i < 5 ; i ++){
li = document.createElement("li");
li.appendChild(document.createTextNode("item"+i));
fragment.appendChild(li);
}
ul.appendChild(fragment);
避免了 for 循环中一直为 ul 添加子节点而造成页面的反复渲染。