JavaScript DOM 编程艺术读书笔记
一、JavaScript简史
XHTML:可扩展的超文本标记语言
DHTML:动态的HTML,是HTML、CSS和JavaScript三种技术相结合的产物
CSS:层叠样式表
DOM:由W3C(万维网联盟)批准并由所有与标准相兼容的Web浏览器支持的第三方技术称为DOM(文档对象模型)。简单的说,DOM是一套对文档的内容
进行抽象和概念化的方法。DOM是一种API(应用编程接口)。
W3C对DOM的定义是:“一个与系统平台和编程语言无关的接口,程序和脚本可以通过这个接口动态地对文档的内容、结构和样式进行访问和修改。”
目前使用的95%以上的浏览器都具备对DOM的内建支持。
二、JavaScript语法
1、把JavaScript编写的代码必须嵌入在一份HTML/XHTML文档中才能得到执行。方法有二:
一是将JavaScript代码插入文档<head>部分的<script>标签间;
二是先把JavaScript代码存入一个独立的文件----建议把.js作为这种文件的扩展名,再利用<script>标签的src属性指向该文件
<script type="text/javascript" src="fileName.js">
</script>
2、JavaScript中的变量和其他语法元素的名字都是区分字母大小写的;
JavaScript语法不允许变量的名字中包含空格或标点符号(但美元符号"$"除外);
JavaScript变量名允许包含字母、数字、美元符号和下划线字符
3、数据类型
字符串:
由零个或多个字符构成。字符可包括字母、数字、标点符号和空格。字符串必须放在引号里----单引号或者双引号均可。但最好根据字符串所
包含的字符来加以选择(看字符串里包含是单引号还是双引号)。但若用双引号就一直用双引号。保持一致性
转义字符"\".如var mood = 'don\'t ask'; 转义后为don't ask 双引号也如此。
布尔值:
千万不要把布尔值用引号括起来。false和'false'、"false"完全是两码事
数组:
除了Array的一般用法外,数组还可以包含数组!数组中的任何一个元素都可以把一个数组作为它的值。如:
var lennon = Array("John",1940,false);
var beatles = Array();
beatles[0] = lennon;
那么beatles数组的第一个元素的值是另外一个数组。此时beatles[0][0] == "John",beatles[0][1] == 1940, beatles[0][2] == false
关联数组
用关联数组来代替上面的数值数组。如:
var lennon = Array();
lennon["name"] = "John";
lennon["year"] = 1940;
lennon["living"] = false;
var beatles = Array();
beatles[0] = lennon;
那么访问元素时就可以用:beatles[0]["name"] == "John",beatles[0]["year"] == 1940等。
当然beatles数组也可以填充为关联数组而不是数值数组
4、变量的作用域
如果在某个函数中使用了var关键字,那个变量就将被视为一个局部变量,它将只存在于这个函数的上下文。反之,如果没有使用var,那个变量就被视
为一全局变量。如果你的脚本里已经存在一个与之同名的变量,这个函数将覆盖那个现有变量的值。
5、对象
内建对象:内建在JavaScript语言里的对象。Math、Date、Array等
宿主对象:由浏览器提供的对象,如Form、Element、Image等
用户定义对象:由程序员自行创建的对象。定义一Person对象等。
document对象
三、DOM
DOM节点分为不同的类型:元素节点、属性节点和文本节点等
DOM四个非常有用的方法:getElementById、getElementsByTagName、getAttribute、setAttribute
1、document.getElementById("id")返回的类型是一个对象Object,该对象对应着文档里的一个特定的元素节点
2、document.getElementsByTagName("TagName")返回的是一个数组,他们分别对应着文档里的一个特定的元素节点.getElementsByTagName()方法允许我们把
一通配符当为它的参数.上面说到的节点每个都是一个对象
3、getAttribute()方法是一个函数,它只是一个参数----你打算查询的属性的名字。不过getAttribute()方法不能通过document对象调用,它只能通过一个
元素节点对象调用它。
4、setAttribute()方法类似于getAttribute()方法,也是一个只能通过元素节点对象调用的函数,但setAttribute()方法需要我们向它传递两个参数
object.setAttribute(attribute,value)
5、DOM其他属性
childNodes:此属性让我们可以从给定文档的节点树里把任何一个元素的所有子元素检索出来。childNodes属性将返回一个数组,这个数组包含给定元素节
点的全体子元素
element.childNodes
nodeValue属性:如果想改变某个文本节点的值,就使用DOM提供的nodeValue属性。它的用途就是检索和设置节点的值
node.nodeValue
但需要注意的细节是:在用nodeValue属性检索description对象的值时,得到的不是包含在这个段落里的文本。而是返回一null值。所以需要检索它的第一
个子节点的nodeValue属性值 如description.childNodes[0].nodeValue 和node.firstChild.nodeValue等价。象对应的有node.lastChild.nodeValue(最后一个值)
四、JavaScript编程原则和良好习惯
要点
预留退路:确保网页在没有JavaScript的情况下也能正常工作
分离JavaScript:把网页的结构和内容与JavaScript脚本的动作行为分开
向后兼容:确保老版本的浏览器不会因为你的JavaScript脚本而死机
1、预留退路
1> 注意:应该只在有绝对必要的情况下才使用弹出窗口,因为这将牵涉到网页的可访问性问题:
浏览器不支持弹出窗口,浏览器的弹出窗口支持功能已被用户禁用,用户使用的屏幕读取软件无法向用户说明弹出了窗口,等等。
因此,如果网页上的某个链接将弹出新窗口,最好在这个链接本身的文字中予以说明
window.open(url,name,features) 第三个参数要掌握一原则:新窗口的浏览功能要少而精
2> "javascript:"伪协议的做法非常不好 如<a href="javascript:popUp('http://www.sina.com.cn');">新浪网</a>
3> 内嵌的事件处理函数如<a href="#" οnclick="popUp('http://www.sina.com.cn/')">新浪网</a>
href="#"只是为了创建一个空链接。实际工作全部由onclick属性负责完成。这种技巧与"javascript:"伪协议做法一样糟糕。若用户禁用了浏览器的
JavaScript功能,这样的链接将毫无用处。
上面第2点和第3点的解决方法为
<a href="http://www.sina.com.cn" οnclick="popUp(this.href);return false;">新浪网</a>
2、分离JavaScript
正如CSS机制中的class或id属性那样,把JavaScript代码调用行为与HTML文档的结构和内容分离开,这样网页就会健壮得多
1> 我们可以在外部JavaScript文件里把一个事件添加到HTML文档中的某个元素上:element.event = action...
2> 若想把一个事件添加到某个带有特定id属性的元素上,用getElementById()方法就可以解决问题:getElementById(id).event = action
如果事情涉及到多个元素,我们可以用getElementsByTagName()和getAttribute()方法把事情添加到有着特定属性的一组元素上,具体步骤如下
(以onclick()事件和popUp()事件为例)
<1> 把文档里的所有链接全放入一个数组里
<2> 遍历数组
<3> 如果某个链接的class属性等于popup,就说明这个链接在被电击时将调用popUp()函数。
于是:
A. 把这个链接的href属性值传递给popUp()函数
B. 取消这个链接的默认行为,不让这个链接把访问者带离当前窗口
上面的JavaScript实现代码如下:
var links = document.getElementsByTagName("a");
for(var i=0;i<links.length;i++) {
if(links[i].className == "popup") {
links[i].click = function(){
popUp(this.getAttribute("href"));
return false;
}
}
}
此种情况要加载window.onLoad事件 这样就昂这些代码在HTML文档全部加载到浏览器之后才开始执行。如下:
window.onLoad = prepareLinks;
function prepareLinks(){
var links = document.getElementsByTagName("a");
for(var i=0;i<links.length;i++) {
if(links[i].className == "popup") {
links[i].click = function(){
popUp(this.getAttribute("href"));
return false;
}
}
}
}
别忘记把popUp()函数也保存到此外部JavaScript文件里去:
function popUp(winURL) {
window.open(winURL,"popup","width=320,height=480");
}
3、向后兼容性
对象检测技术(浏览器嗅探技术已经越来越落伍,逐渐被对象检测技术所取代)
由于浏览器的不同,需要进行对象检测 方法为:if(!method) return false;
如下:
window.onLoad = function(){
if(!document.getElementsByTagName) return false;//在这儿!关键代码 若有多个判断可以见"||"符号
var links = document.getElementsByTagName("a");
for(var i=0;i<links.length;i++) {
if(links[i].className == "popup") {
links[i].click = function(){
popUp(this.getAttribute("href")); //这儿的关键字this代表着在此时此刻与onclick方法相关联的那个元素
return false; //意思是"按照这个链接没被点击的情况采取行动"
}
}
}
}
4、其他注意事项
若加载页面时出现 window.onload = firstFunction; window.onload = secondFunction; 此时最后的secondFunction函数才会被实际执行
若要把多个JavaScript函数绑定到onload事件处理函数上,有两种方法
1> window.onload = function() {
firstFunction();
secondFunction();
}
2> 使用函数AddLoadEvent(),其完成的操作为:
A. 把现有的window.onload事件处理函数的值存入变量oldonload
B. 如果在这个处理函数上还没有绑定任何函数,就像平时那样把新函数添加给它
C. 如果在这个处理函数上已经邦定理一些函数,就把新函数追加到现有指令的末尾
实现方法为:AddLoadEvent(firstFunction); AddLoadEvent(secondFunction);
其中:
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
oldonload();
func();
}
}
}
五、动态创建HTML内容
要点
用来动态创建HTML内容的“老”技巧:document.write()方法和innerHTML属性
深入剖析DOM方法:createElement()、createTextNode()、appendChild()和insertBefore().
1、document.write()方法:方便快捷的把字符串插入到文档里
2、innerHTML 属性可以用来读、写某给定元素里的HTML内容,innerHTML属性是一项专利技术,不是一项业界标准。
3、createElement()方法:创建一个新的元素。用法为:document.createElement(nodeName)
4、appendChild()方法:把新建的节点插入某个文档的节点数的最简单的办法是,让它成为这个文档的某个现有节点的一个子节点。
appendChild()方法的用法为: parent.appendChild(child) 例如要实现元素P成为testDiv元素的一个子节点
var para = document.createElement("P"); //新创建一P元素
var testDiv = document.getElementById("testDiv"); //提取出来testDiv节点
testDiv.appendChild(para); //把元素P成为testDiv元素的子节点
5、createTextNode()方法:创建一个文本节点
用法为:document.createTextNode(text) 如:document.createTextNode("Hello world"); //创建一个内容为"Hello world"的文本节点
用appendChild()方法把文本节点插入为某个现有元素的子节点
接4:
var para = document.createElement("P"); //新创建一P元素
var testDiv = document.getElementById("testDiv"); //提取出来testDiv节点
testDiv.appendChild(para); //把元素P成为testDiv元素的子节点
var txt = document.createTextNode("Hello world"); //创建一个内容为"Hello world"的文本节点
para.appendChild(txt); //用appendChild()方法把txt这个文本节点插入为现有元素P的子节点上去
也可以把上面的步骤交换下位置,变为:
var para = document.createElement("P"); //新创建一P元素
var txt = document.createTextNode("Hello world"); //创建一个内容为"Hello world"的文本节点
para.appendChild(txt); //用appendChild()方法把txt这个文本节点插入为现有元素P的子节点上去
var testDiv = document.getElementById("testDiv"); //提取出来testDiv节点
testDiv.appendChild(para); //把元素P成为testDiv元素的子节点
6、insertBefore()方法:将把一个新元素插入到一个现有元素的前面
调用语法为:
parentElement.insertBefore(newElement,targetElement);
其中:newElement是想插入的元素;targetElement是想把新元素newElement插入到哪个现有元素(targetElement)的前面;
parentElement是上面两元素newElement、targetElement共同的父元素(这儿的父元素一般是targetElement元素的parentNode属性)如:
var gallery = document.getElementById("imagegallery");
gallery.parentNode.insertBefore(placeholder,gallery); //把placeholder元素插入到图片清单的前面
gallery.parentNode.insertBefore(description,gallery); //把description元素插入到图片清单的前面
但DOM中没有insertAfter()方法。自身定义insertAfter()方法。如下:
function insertAfter(newElement,targetElement) {
var parent = targetElement.parentNode; //把目标元素的parentNode属性值提取到变量parent里
if(parent.lastChild == targetElement) { //检查目标元素是不是parent的最后一个子元素
parent.appendChild(newElement);
} else {
parent.insertBefore(newElement,targetElement.nextSibling); //targetElement.nextSibling为目标元素的下一个子元素即目标元素的下一个兄弟节点
}
}
7、程序代码
1> showPic.js代码如下
//showPic()方法
function showPic(whichpic) {
if (!document.getElementById("placeholder")) return true;
var source = whichpic.getAttribute("href");
var placeholder = document.getElementById("placeholder");
placeholder.setAttribute("src",source);
if (!document.getElementById("description")) return false;
if (whichpic.getAttribute("title")) {
var text = whichpic.getAttribute("title");
} else {
var text = "";
}
var description = document.getElementById("description");
if (description.firstChild.nodeType == 3) {
description.firstChild.nodeValue = text;
}
return false;
}
//此函数负责处理有关的事件。将遍历imagegallery清单里的每个链接,并给它加上一个onclick事件处理函数。当用户点击这个链接中的某一个时
//就会调用showPic()函数
function prepareGallery() {
if (!document.getElementsByTagName) return false;
if (!document.getElementById) return false;
if (!document.getElementById("imagegallery")) return false;
var gallery = document.getElementById("imagegallery");
var links = gallery.getElementsByTagName("a");
for ( var i=0; i < links.length; i++) {
links[i].onclick = function() {
return showPic(this);
}
links[i].onkeypress = links[i].onclick;
}
}
//通用型函数,在很多场合都能派上用场
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
oldonload();
func();
}
}
}
//通用型函数,在很多场合都能派上用场
function insertAfter(newElement,targetElement) {
var parent = targetElement.parentNode; //把目标元素的parentNode属性值提取到变量parent里
if(parent.lastChild == targetElement) { //检查目标元素是不是parent的最后一个子元素
parent.appendChild(newElement);
} else {
parent.insertBefore(newElement,targetElement.nextSibling); //targetElement.nextSibling为目标元素的下一个子元素即目标元素的下一个兄弟节点
}
}
//实现 <img id="placeholder" src="../Images/placeholder.gif" alt="my image gallery" /><p id="description">Choose an image.</p>的功能
//创建一个img元素和一个p元素。这个函数将把这些新创建的元素插入到5_BackGallery.htm文档的节点树里----当然,新元素会被插入到imagegallery清单的后面
function preparePlaceholder() {
if(!document.createElement) return false;
if(!document.createTextNode) return false;
if(!document.getElementById) return false;
if(!document.getElementsByTagName) return false;
var placeholder = document.createElement("img");
placeholder.setAttribute("id","placeholder");
placeholder.setAttribute("src","../Images/placeholder.gif");
placeholder.setAttribute("alt","My image Gallery");
var description = document.createElement("p");
description.setAttribute("id","description");
var descText = document.createTextNode("Choose an Image");
description.appendChild(descText);
var gallery = document.getElementById("imagegallery");
insertAfter(placeholder,gallery); //将placeholder元素插入到gallery元素的后面
insertAfter(description,placeholder); //将description元素插入到placeholder元素的后面
// gallery.parentNode.insertBefore(placeholder,gallery); 将placeholder元素插入到gallery元素的前面
// gallery.parentNode.insertBefore(description,gallery);
// document.getElementsByTagName("body")[0].appendChild(placeholder); //将placeholder元素插入到位于文档末尾的</body>标签的签名
// document.getElementsByTagName("body")[0].appendChild(description); //将description元素插入到位于文档末尾的</body>标签的签名
// //或者
// document.body.appendChild(placeholder); //将placeholder元素插入到位于文档末尾的</body>标签的签名
// document.body.appendChild(description); //将description元素插入到位于文档末尾的</body>标签的签名
}
addLoadEvent(preparePlaceholder);
addLoadEvent(prepareGallery);
2> 5_BackGallery.htm代码如下
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>重回"JavaScript美术馆"</title>
<script type="text/javascript" src="../JavaScript/showPic.js"></script>
<link rel="stylesheet" href="../CSS/layout.css" type="text/css" media="screen" ></link>
</head>
<body>
<h1>SnapShots</h1>
<ul id="imagegallery">
<li>
<a href="../Images/fireworks.jpg" title="A fireworks display">
<img src="../Images/thumbnail_fireworks.jpg" alt="Fireworks" /></a>
</li>
<li>
<a href="../Images/coffee.jpg" title="A cup of black coffee" >
<img src="../Images/thumbnail_coffee.jpg" alt="Coffee" /></a>
</li>
<li>
<a href="../Images/rose.jpg" title="A red, red rose">
<img src="../Images/thumbnail_rose.jpg" alt="Rose" /></a>
</li>
<li>
<a href="../Images/bigben.jpg" title="The famous clock">
<img src="../Images/thumbnail_bigben.jpg" alt="Big Ben" /></a>
</li>
</ul>
<!-- <img id="placeholder" src="../Images/placeholder.gif" alt="my image gallery" />
<p id="description">Choose an image.</p>-->
</body>
</html>
六、充实文档的内容
要点
一个为文档创建“缩略词语表”的函数
一个为文档创建“文献来源链接”的函数
一个为文档创建“快速访问键清单”的函数
1、循序渐进原则----即为这样一种思考问题的方法:从最核心的内容开始,逐步添加额外的功能。应该先用标记语言给核心内容加上正确的标记以使其获得
正确的结构;然后逐步充实被加上了正确标记的内容。充实的内容既可以是通过CSS样式表实现各种呈现效果,也可以是通过DOM脚本添加各种操作行为。
2、for/in循环
for/in循环的独特之处是,它可以把某个数组的下标(键字)临时地赋值给一个变量:
for(variable in array)
在for/in循环进入第一次循环时,变量variable将被赋值为数组array的第一个元素的下标值;在进入第二次循环时,变量variable将被赋值为数组array
的第二个元素的下标值;一次类推,直到遍历完数组array里的所有元素为止
3、在需要对文档里的现有信息进行检索时,以下DOM方法最有用:
getElementById()
getElementsByTagName()
getAttribute()
4、在需要把信息添加到文档里去时,以下DOM方法最有用:
createElement()
createTextNode()
appendChild()
insertBefore()
setAttribute()
七、CSS-DOM
要点
style属性
如何检索样式信息
如何改变样式
1、三位一体的网页(结构层、表示层、行为层)
结构层由HTML或XHTML之类的标记语言负责创建。
表示层由CSS负责创建。CSS对“如何显示有关内容”的问题做出回答
行为层负责回答“内容应该如何对事件作出反应”这一问题。这是JavaScript语言和DOM主宰的领域
2、style属性 文档的每个元素节点都有一属性style。style属性包含着元素的样式信息,查询这个属性将返回一个对象而不是一个简单的字符串。
样式信息都存放在这个对象的属性里:element.style.property
其中style属性是一个对象
3、样式信息的检索
element.style.color
element.style.font-family是错误的(当中有减号,JavaScript会解释成一个减法运算)。DOM解决这个问题的方法是,采用“Camel记号”来
表示那些名字里有多少单词的CSS属性。所以上面的变成element.style.fontFamily即可。
4、不管CSS样式属性的名字里有多少个连字符,DOM一律采用“Camel记号”来表示它们 如CSS中的background-color将对应DOM属性backgroundColor
5、内嵌样式
通过style属性检索样式信息有个很大的局限性:style属性只能返回那些内嵌在HTML内容里的样式信息。换句话说,只有把CSS style属性插入到HTML代码
里,才可以用DOM style属性去查询那些信息
6、设置样式信息
element.style.property = value
注意 style对象的各个属性的值永远是一个字符串。所以style对象的属性值必须放在引号里,单引号或者双引号都可。
7、CSS声明样式信息的具体做法主要有三种:
A、为同类型的所有元素(比如p元素)统一地声明一种样式,如下所示:
p{
font-size:1em;
}
B、为有着特定class属性的所有元素统一地声明一种样式,如下所示:
.fireprint{
font-size:1.2em;
}
C、为某个有着独一无二的id属性的元素单独声明一种样式,如下所示:
#intro{
font-size:1.2em;
}
例题:通过一个遍历一个节点集合去设置有关元素的样式信息(stripeTables()函数)
function stripeTables() {
if (!document.getElementsByTagName) return false;
var tables = document.getElementsByTagName("table");
for (var i=0; i<tables.length; i++) {
var odd = false;
var rows = tables[i].getElementsByTagName("tr");
for (var j=0; j<rows.length; j++) {
if (odd == true) {
//rows[j].style.backgroundColor = "#ffc";
addClass(rows[j],"odd");
odd = false;
} else {
odd = true;
}
}
}
}
function addClass(element,value) {
if(!element.className) {
element.className = value;
} else {
newClassName = element.className;
newClassName += " ";
newClassName += value;
element.className = newClassName;
}
}
8、对事件做出响应(8_Itinerary.htm)
若想实现让某个表格行在鼠标指针悬停在它的上方时称选中状态(字体变为粗体):
CSS实现方式为:
tr:hover{
font-weight:bold;
}
但只能在一部分浏览器中看到此效果
所以DOM实现此事件,具体为:
function highlightRows(){
if(!document.getElementsByTagName) return false;
var rows = document.getElementsByTagName("tr");
for(var i=0;i<rows.length;i++) {
rows[i].onmouseover = function() {
this.style.fontWeight = "bold";
}
rows[i].onmouseout = function() {
this.style.fontWeight = "normal";
}
}
}
此函数实现的功能是:在对事件做出响应时设置有关元素的样式信息
八、用JavaScript实现动画效果
要点
何为动画
用动画丰富网页的浏览效果
让动画效果更流畅
1、时间
A、setTimeout()函数
JavaScript函数setTimeout()能够让某个函数在经过一段预定的时间之后才开始执行。这个函数带有两个参数:第一个参数是一个字符串,其内容是将
要执行的那个函数的名字;第二个参数是一个数值,它以毫秒为单位设定了需要经过多长时间才开始执行由第一个参数所给出的函数:
setTimeout("function",interval)
在绝大多数时候,把这个函数调用赋值给一个变量将是个好主意:
variable = setTimeout("function",interval);
若打算在interval等待时间里取消此功能,可以通过clearTimeout(variable)实现。
例如下面一函数
function moveElement(elementID,final_x,final_y,interval) {
if(!document.getElementById) return false;
if(!document.getElementById(elementID)) return false;
var elem = document.getElementById(elementID);
if(elem.movement) {
clearTimeout(elem.movement);
}
var xpos = parseInt(elem.style.left);
var ypos = parseInt(elem.style.top);
if(xpos == final_x && ypos == final_y){
return true;
}
if(xpos < final_x) {
xpos++;
}
if(xpos > final_x) {
xpos--;
}
if(ypos < final_y) {
ypos++;
}
if(ypos > final_y) {
ypos--;
}
elem.style.left = xpos + "px";
elem.style.top = ypos + "px";
var repeat = "moveElement('" + elementID + "'," + final_x + "," + final_y + "," + interval + ")";
elem.movement = setTimeout(repeat,interval);
}
2、Form对象
form.elements.length返回的是包含在某给定form元素里的表单元素的总个数
form.elements属性。与childNodes属性不同,childNodes属性也是一数组,它包含着某给定元素的所有子节点。而elements数组将只返回input元素、select元素、textarea元素和其他表单字段
elements数组里的每个表单元素都有自己的一套属性。比如说,表单元素的value属性包含该元素的当前值:
element.value 相当于 element.getAttribute("value")
还有一属性:element.defaultValue: 它包含着该表单元素的初始值
3、indexOf()方法 的基本用途是,找出一个字符串在另一个字符串里第一次出现的位置。如果找到了搜索字符串,它将返回那个位置;若未找到,将返回-1。
附录 DOM方法和属性
DOM方法
1、创建节点
1> createElement()
createElement()方法将按照给定的标签名创建一个新的元素节点。这个方法的返回值是一个指向新建元素节点的引用指针
reference = document.createElement(element)
createElement()方法所返回的引用指针指向一个节点对象。它是一个元素节点,所以它的nodeType属性值将等于1
var para = document.createElement("p");
在这个例子里,para.nodeType返回的值将是1。para.nodeName 返回的值将是p或P。
用createElement()方法创建出来的新元素节点不会被自动添加到文档里。新节点没有nodeParent属性,它只是一个存在于JavaScript上下文里的DocumentGragment对象。
如果想把这个DocumentGragment对象添加到你的文档里,则需要使用appendChild()或insertBefore()方法或者replaceChild()方法
接上 document.body.appendChild(para);
2> createTextNode()
createTextNode()方法将创建一个包含着给定文本的新文本节点。这个方法的返回值是一个指向新建文本节点的引用指针:
reference = document.createTextNode(text) //此方法只有一个参数,新建文本节点所包含的文本字符串
var reference = document.createTextNode("Hello World");
createTextNode()方法所返回的引用指针指向一个节点对象。它是一文本节点,所以其nodeType的属性值是3。reference.nodeType返回的值是3。reference.nodeName返回的值将是#text.
createTextNode()方法创建出来的新元素节点不会被自动添加到文档里。新节点没有ParentNode属性。如果想把这个DocumentGragment对象添加到你的文档里,则需要使用appendChild()或insertBefore()方法或者replaceChild()方法
2、复制节点
1> cloneNode()
cloneNode()方法将为给定节点创建一副本。这个方法的返回值是一个指向新建克隆节点的引用指针:
reference = node.cloneNode(deep) //此方法只有一个布尔型的参数,它的可取值只能是true或false。这个参数决定着是否要把被复制节点的子节点也一同复制到新建节点里去。
3、插入节点
1> appendChild()方法:该方法将给元素节点追加一个字节点
reference = element.appendChild(newChild) //给定子节点newChild将成为给定元素节点element的最后一个字节点,此方法返回值是一个指向新增子节点的引用指针
这个方法通常与用来创建新节点的createElement()和createTextNode()方法配合使用。如下:
var para = document.createElement("p"); //createElement()方法创建一个para文本元素
var message = document.createTextNode("hello world"); //createTextNode()方法创建一个message文本节点
para.appendChild(message); //appendChild()方法把message文本节点插入到para元素节点
document.body.appendChild(para); //把para元素(以及它的子节点message)插入文档的结构
2> insertBefore()
insertBefore()方法将把一个给定节点插入到一个给定元素节点的给定子节点的前面。
reference = element.insertBefore(newNode,targetNode); //节点newNode将被插入元素节点element并出现在节点targetNode的前面。
节点targetNode必须是element元素的一个子节点。若targetNode节点未给出。newNode节点就将被追加为element元素的最后一个子节点----从效果上看相当于调用了appendChild()方法
DOM中无和insertBefore()相对应的insertAfter()方法。但可以定义此方法作为一公共方法。用途很多。具体定义如下:
function insertAfter(newElement,targetElement) {
var parent = targetElement.parentNode;
if(parent.lastChild == targetElement) {
parent.appendChild(newElement);
} else {
parent.insertBefore(newElement,targetElement.nextSibling);
}
}
上面的appendChild()和insertBefore()两个方法不仅可以用来追加新创建的元素,还可以用来挪动文档中的现有元素。如下:
var message = document.getElementById("fineprint");
var container = document.getElementById("content");
container.appendChild(message); //此种情况是先把id属性是fineprint的元素从文档树上被删除,然后再作为content元素的最后一个子节点被重新插入到新位置。
//下面的方法和appendChild()实现的功能类似
//var announcement = document.getElementById("headline");
//container.insertBefore(announcement,message);
4、 删除节点
removeChild() 该方法将从一个给定元素里删除一个子节点
reference = element.removeChild(node) //此方法的返回值是一个指向已被删除的子节点的引用指针。
当某个节点被removeChild()方法删除时,这个节点所包含的所有子节点将同时被删除
var container = document.getElementById("content");
var message = document.getElementById("fineprint");
container.removeChild(message); //用removeChild()方法从content元素里把fineprint元素删掉
如果想删除某个节点,但不知道它的父节点是哪一个,parentNode属性可以帮上大忙
var message = document.getElementById("fineprint");
var container = message.parentNode;
container.removeChild(message);
5、替换节点
replaceChild() 该方法将把一个给定父元素里的一个子节点替换为另外一个节点
reference = element.replaceChild(newChild,oldChild); //注意oldChild节点必须是element元素的一个子节点
6、设置属性节点
setAttribute() 该方法将为给定元素节点添加一个新的属性值或是改变它的现有属性的值
element.setAttribute(attributeName,attributeValue); //属性的名字和值必须以字符串的形式传递给此方法
7、查找节点
1> getAttribute() 该方法将返回一个给定元素的一个给定属性节点的值
attributeValue = element.getAttribute(attributeName); //给定属性的名字必须以字符串的形式传递给这个方法,给定属性的值将以字符串的形式返回。若属性不存在,返回一空字符串
2> getElementById() 该方法的用途是寻找一个有着给定id属性值的元素
element = document.getElementById(ID); //若不存在此ID,则返回null,此方法只能用于document对象
3> getElementsByTagName() 该方法的用途是寻找有着给定标签名的所有元素
elements = document.getElementsByTagName(tagName); //此方法返回一个节点集合,这个集合可以当作一个数组来处理。此数组里的每个元素都是一对象。它们都有着nodeName,nodeType,parentNode,childNodes等属性
例 var paras = document.getElementsByTagName("p");
for(var i=0;i<paras.length;i++) {
paras[i].setAttribute("title","");
}
4> hasChildNodes() 该方法可用来检查一个给定元素是否有子节点
booleanValue = element.hasChildNodes; //此方法将返回一个布尔值true或false。 文本节点和属性节点都不可能再包含任何子节点,所以对这两类节点使用hasChildNodes方法返回值永远是false。
hasChildNodes方法无法返回某给定元素的子节点----子节点可以用这个元素的childNodes属性去检索。若hasChildNodes返回是false,childNodes属性将是一空数组。
8、节点的属性
1> nodeName 此属性将返回一个字符串,其内容是给定节点的名字
name = node.nodeName;
注意 若给定节点是一个元素节点,nodeName属性将返回这个元素的名字,这在效果上相当于tagName属性
若给定节点是一个属性节点,nodeName属性将返回这个属性的名字
若给定节点是一个文本节点,nodeName属性将返回一个内容为#text的字符串
nodeName属性是一只读属性
2> noeType 此属性将返回一个整数,这个整数代表着给定节点的类型
integer = node.nodeType //元素节点nodeType为1,属性节点nodeType为2,文本节点nodeType为3
nodeType属性是一个只读属性
3> nodeValue 该属性将返回给定节点的当前值
value = node.nodeValue //此属性返回一个字符串
注意 若给定节点是一个属性节点,nodeValue属性将返回这个属性的值
若给定节点是一个文本节点,nodeValue属性将返回这个文本节点的内容
若给定节点是一个元素节点,nodeValue属性将返回null
nodeValue属性是一个读/写属性。不过,你不能对一个已经被定义为null的值进行设置。换句话说,你不能为元素节点的nodeValue属性设置一个值。你可以为文本节点的nodeValue属性设置一个值
9、遍历节点树
1> childNodes 该属性将返回一个数组,这个数组由给定元素节点的子节点构成
nodeList = node.childNodes; //此属性所返回的数组是一个nodeList集合
注意 文本节点和属性节点都不可能再包含任何子节点,所以它们的childNodes属性永远会返回一个空数组
node.childNodes.length //获得某个元素有多少子节点
2> firstChild //此属性将返回一个给定元素节点的第一个子节点
reference = node.firstChild
等价于
reference = node.childNodes[0]
3> lastChild 该属性将返回一个给定元素节点的最后一个子节点
reference = node.lastChild
等价于
reference = node.childNodes[elementNode.childNodes.length - 1]
4> nextSibling 该属性将返回一个给定节点的下一个子节点
reference = node.nextSibling
5> parentNode 该属性将返回一个给定节点的父节点
reference = node.parentNode
注意 parentNode属性返回的节点永远是一个元素节点,因为只有元素节点才有可能包含子节点。唯一的例外是document节点。它没有父节点
6> previousSibling 该属性将返回一个给定节点的上一个子节点
10、节点的定义
如<p title="a gentle reminder">Don't forget to buy this stuff.</p>
元素节点:如<body> <p> <ul>等就是元素节点
文本节点:上面的Don't forget to buy this stuff.就是文本节点。主要是内容
属性节点:title="a gentle reminder"是属性节点