1. 程式人生 > >JavaScript的DOM操作(02)

JavaScript的DOM操作(02)

JavaScript的DOM操作(02)

1.節點的新增操作

<script type="text/javascript">
			
			//新建立一個元素節點, 並把該節點新增為文件中指定節點的子節點
			window.onload = function(){
				alert(1);
				
				//1. document.createElement(elementTagName)
				//新建立一個元素節點, 返回值為指向元素節點的引用
				//<li></li>
				var liNode = document.createElement("li");
				
				//2. 建立 "廈門" 的文字節點
				//document.createTextNode(string) 建立一個文字節點
				//引數為文字值, 返回該文字節點的引用. 
				var xmText = document.createTextNode("廈門");
				//<li>廈門</li>
				liNode.appendChild(xmText);
				
				var cityNode = document.getElementById("city");
				//2. elementNode.appendChild(newChild): 為 elementNode
				//新新增 newChild 子節點, 該子節點將作為 elementNode 的最後
				//一個子節點. 
				cityNode.appendChild(liNode);
			}
		
		</script>
<body>
		<p>你喜歡哪個城市?</p>
		<ul id="city"><li id="bj" name="BeiJing">北京</li>
			<li>上海</li>
			<li>東京</li>
			<li>首爾</li>
		</ul>
		
		<br><br>
		<p>你喜歡哪款單機遊戲?</p>
		<ul id="game">
			<li id="rl">紅警</li>
			<li>實況</li>
			<li>極品飛車</li>
			<li>魔獸</li>
		</ul>
		
		<br><br>
		gender: 
			<input type="radio" name="gender" value="male"/>Male
			<input type="radio" name="gender" value="female"/>Female
	
		<br><br>
		name: <input type="text" name="username" value="xxx"/>
		
	</body>

2.節點的互換操作

<script type="text/javascript">
			
			//測試 replaceChild 方法
			window.onload = function(){
				
				alert(1);
				
				var bjNode = document.getElementById("bj");
				var rlNode = document.getElementById("rl");
				var gameNode = document.getElementById("game");
				
				gameNode.replaceChild(bjNode, rlNode);
				
				//replaceEach(bjNode, rlNode);
				
				/*
				var cityNode = document.getElementById("city");
				//cityNode.replaceChild(rlNode, bjNode);
				
				//實現 bj 節點和 rl 節點的互換. 
				var gameNode = document.getElementById("game");
				
				//克隆 bjNode
				//cloneNode(deep) 若 deep 為true, 則可以克隆子節點
				var bjNode2 = bjNode.cloneNode(true);
				gameNode.replaceChild(bjNode2, rlNode);
				
				alert(2);
				
				cityNode.replaceChild(rlNode, bjNode);
				*/
			}
			
			//自定義互換兩個節點的函式
			function replaceEach(aNode, bNode){
				//1. 獲取 aNode 和 bNode 的父節點. 使用 parentNode 屬性
				var aParent = aNode.parentNode;
				var bParent = bNode.parentNode;
				
				if(aParent && bParent){
					//2. 克隆 aNode 或 bNode
					var aNode2 = aNode.cloneNode(true);
					
					//3. 分別呼叫 aNode 的父節點和 bNode 的父節點的 replaceChild()
					//方法實現節點的互換
					bParent.replaceChild(aNode2, bNode);
					aParent.replaceChild(bNode, aNode);
				}
			}
		
		</script>
<body>
		<p>你喜歡哪個城市?</p>
		<ul id="city"><li id="bj" name="BeiJing">北京</li>
			<li>上海</li>
			<li>東京</li>
			<li>首爾</li>
		</ul>
		
		<br><br>
		<p>你喜歡哪款單機遊戲?</p>
		<ul id="game">
			<li id="rl">紅警</li>
			<li>實況</li>
			<li>極品飛車</li>
			<li>魔獸</li>
		</ul>
		
		<br><br>
		gender: 
			<input type="radio" name="gender" value="male"/>Male
			<input type="radio" name="gender" value="female"/>Female
	
		<br><br>
		name: <input type="text" name="username" value="xxx"/>
		
	</body>

3.節點的移除

<script type="text/javascript">
			
			//測試 removeChild() 方法: 刪除節點
			window.onload = function(){
				
				/*
				alert("1");
				
				var bjNode = document.getElementById("bj");
				bjNode.parentNode.removeChild(bjNode);
				*/
				
				//為每個 li 節點新增一個 confirm(確認對話方塊): 確定要刪除 xx 的資訊嗎?
				//若確定, 則刪除
				
				var liNodes = document.getElementsByTagName("li");
				
				for(var i = 0; i < liNodes.length; i++){
					liNodes[i].onclick = function(){
						var flag = confirm("確定要刪除" + 
								this.firstChild.nodeValue + "的資訊嗎?");
						
						if(flag){
							this.parentNode.removeChild(this);
						}
					}
				}
				
				//var flag = confirm("確定要刪除嗎?");
				//alert(flag);
			}
		
		</script>
<body>
		<p>你喜歡哪個城市?</p>
		<ul id="city"><li id="bj" name="BeiJing">北京</li>
			<li>上海</li>
			<li>東京</li>
			<li>首爾</li>
		</ul>
		
		<br><br>
		<p>你喜歡哪款單機遊戲?</p>
		<ul id="game">
			<li id="rl">紅警</li>
			<li>實況</li>
			<li>極品飛車</li>
			<li>魔獸</li>
		</ul>
		
		<br><br>
		gender: 
			<input type="radio" name="gender" value="male"/>Male
			<input type="radio" name="gender" value="female"/>Female
	
		<br><br>
		name: <input type="text" name="username" value="xxx"/>
		
	</body>

4.節點的插入

<script type="text/javascript">
			
			//測試 insertBefore() 插入節點
			//該方法除了進行插入外, 還有移動節點的功能. 
			window.onload = function(){
				
				alert("abc");
				
				//1. 把 #rl 插入到  #bj 節點的前面
				
				var cityNode = document.getElementById("city");
				var bjNode = document.getElementById("bj");
				var rlNode = document.getElementById("rl");
				
				//cityNode.insertBefore(rlNode, bjNode);				
				
				var refNode = document.getElementById("se");
				//var refNode = document.getElementById("dj");
				insertAfter(rlNode, refNode);
			}
			
			//把 newNode 插入到 refNode 的後面
			function insertAfter(newNode, refNode){
				//1. 測試 refNode 是否為其父節點的最後一個子節點
				var parentNode = refNode.parentNode;
				if(parentNode){
					var lastNode = parentNode.lastChild;
					
					//2. 若是: 直接把 newNode 插入為 refNode 父節點的最後一個子節點. 
					if(refNode == lastNode){
						parentNode.appendChild(newNode);
					}
					//3. 若不是: 獲取 refNode 的下一個兄弟節點, 然後插入到其下一個兄弟
					//節點的前面.
					else{
						var nextNode = refNode.nextSibling;
						parentNode.insertBefore(newNode, nextNode);
					}
				}
			}
		
		</script>
<body>
		<p>你喜歡哪個城市?</p>
		<ul id="city"><li id="bj" name="BeiJing">北京</li>
			<li>上海</li>
			<li id="dj">東京</li>
			<li id="se">首爾</li>
		</ul>
		
		<br><br>
		<p>你喜歡哪款單機遊戲?</p>
		<ul id="game">
			<li id="rl">紅警</li>
			<li>實況</li>
			<li>極品飛車</li>
			<li>魔獸</li>
		</ul>
		
		<br><br>
		gender: 
			<input type="radio" name="gender" value="male"/>Male
			<input type="radio" name="gender" value="female"/>Female
	
		<br><br>
		name: <input type="text" name="username" value="xxx"/>
		
	</body>

5.測試 innerHTML 屬性

<script type="text/javascript">
			
			//測試 innerHTML 屬性
			window.onload = function(){
				var cityNode = document.getElementById("city");
				alert(cityNode.innerHTML);
				
				//互換 #city 節點和 #game 節點中的內容. 
				var tempHTML = cityNode.innerHTML;
				var gameNode = document.getElementById("game");
				
				cityNode.innerHTML = gameNode.innerHTML;
				gameNode.innerHTML = tempHTML;
			}
			
		
		</script>
<body>
		<p>你喜歡哪個城市?</p>
		<ul id="city"><li id="bj" name="BeiJing">北京</li>
			<li>上海</li>
			<li id="dj">東京</li>
			<li id="se">首爾</li>
		</ul>
		
		<br><br>
		<p>你喜歡哪款單機遊戲?</p>
		<ul id="game">
			<li id="rl">紅警</li>
			<li>實況</li>
			<li>極品飛車</li>
			<li>魔獸</li>
		</ul>
		
		<br><br>
		gender: 
			<input type="radio" name="gender" value="male"/>Male
			<input type="radio" name="gender" value="female"/>Female
	
		<br><br>
		name: <input type="text" name="username" value="x"/>
		
	</body>

6.總結

1. 節點及其型別:
	1). 元素節點
	2). 屬性節點: 元素的屬性, 可以直接通過屬性的方式來操作. 
	3). 文字節點: 是元素節點的子節點, 其內容為文字. 
	
2. 在 html 文件的什麼位置編寫 js 程式碼?
	
	0). 直接在 html 頁面中書寫程式碼.
		<button id="button" onclick="alert('hello world');">Click Me!</button>
		缺點: 
			①. js 和 html 強耦合, 不利用程式碼的維護
			②. 若 click 相應函式是比較複雜的, 則需要先定義一個函式, 然後再在 onclick 屬性中完成對函式的引用, 比較麻煩

	1). 一般地, 不能在 body 節點之前來直接獲取 body 內的節點, 因為此時 html 文件樹還沒有載入完成, 
	    獲取不到指定的節點:
	
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<title>Untitled Document</title>
		<script type="text/javascript">
			var cityNode = document.getElementById("city");
			//列印結果為 null.
			alert(cityNode);
		</script>
	</head>
	<body>
	......
	
	2). 可以在整個 html 文件的最後編寫類似程式碼, 但這不符合習慣
	
	3). 一般地, 在 body 節點之前編寫 js 程式碼, 但需要利用 window.onload 事件, 
	    該事件在當前文件完全載入之後被觸發, 所以其中的程式碼可以獲取到當前文件的任何節點.
	    
	    <head>
			<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
			<title>Untitled Document</title>
			<script type="text/javascript">
				window.onload = function(){
					var cityNode = document.getElementById("city");
					alert(cityNode);
				};
			</script>
		</head>
		<body>
		......

3. 如何來獲取元素節點:

	1). **document.getElementById: 根據 id 屬性獲取對應的單個節點

	2). **document.getElementsByTagName: 
	根據標籤名獲取指定節點名字的陣列, 陣列物件 length 屬性可以獲取陣列的長度

	3). document.getElementsByName: 
	根據節點的 name 屬性獲取符合條件的節點陣列, 
	但 ie 的實現方式和 W3C 標準有差別: 
	在 html 文件中若某節點(li)沒有 name 屬性, 
	則 ie 使用 getElementsByName 不能獲取到節點陣列, 但火狐可以. 

	4). 其它的兩個方法, ie 根本就不支援, 所以不建議使用  
	
4. 獲取屬性節點:
	1). **可以直接通過 cityNode.id 這樣的方式來獲取和設定屬性節點的值

	2). 通過元素節點的 getAttributeNode 方法來獲取屬性節點,
	         然後在通過 nodeValue 來讀寫屬性值 
	
5. 獲取元素節點的子節點(**只有元素節點才有子節點!!):
	1). childNodes 屬性獲取全部的子節點, 但該方法不實用. 因為如果要獲取指定的節點
	的指定子節點的集合, 可以直接呼叫元素節點的 getElementsByTagName() 方法來獲取. 
	2). firstChild 屬性獲取第一個子節點
	3). lastChild  屬性獲取最後一個子節點		
	
6. 獲取文字節點:
	1). 步驟: 元素節點 --> 獲取元素節點的子節點
	2). 若元素節點只有文字節點一個子節點, 
	例如 <li id="bj" name="BeiJing">北京</li>, <p>你喜歡哪個城市?</p>, 
	可以先獲取到指定的元素節點 eleNode, 
	然後利用 eleNode.firstChild.nodeValue 的方法來讀寫其文字節點的值		



7. 節點的屬性:
	1). nodeName: 代表當前節點的名字. 只讀屬性. 
	**如果給定節點是一個文字節點, nodeName 屬性將返回內容為 #text 的字串
	2). nodeType:返回一個整數, 這個數值代表著給定節點的型別. 
	只讀屬性. 1 -- 元素節點, 2 -- 屬性節點, 3 -- 文字節點
  **3). nodeValue:返回給定節點的當前值(字串). 可讀寫的屬性
		①. 元素節點, 返回值是 null.
		②. 屬性節點: 返回值是這個屬性的值
		③. 文字節點: 返回值是這個文字節點的內容	
		
	    
8. 建立一個元素節點:
	1). createElement(): 按照給定的標籤名建立一個新的元素節點. 方法只有一個引數:被建立的元素節點的名字, 是一個字串.
	                     方法的返回值:是一個指向新建節點的引用指標. 返回值是一個元素節點, 所以它的 nodeType 屬性值等於 1.
                           **新元素節點不會自動新增到文件裡, 它只是一個存在於 JavaScript 上下文的物件.
                         
9. 建立一個文字節點:
	1). createTextNode(): 建立一個包含著給定文字的新文字節點. 這個方法的返回值是一個指向新建文字節點引用指標. 它是一個文字節點, 所以它的 nodeType 屬性等於 3.
	                         方法只有一個引數:新建文字節點所包含的文字字串. 新元素節點不會自動新增到文件裡
	                         
10. 為元素節點新增子節點:
	1). appendChild(): var reference = element.appendChild(newChild): 給定子節點 newChild 將成為給定元素節點 element 的最後一個子節點.
	                      方法的返回值是一個指向新增子節點的引用指標.		    
	                      
11. 節點的替換:
	1). replaceChild(): 把一個給定父元素裡的一個子節點替換為另外一個子節點
			var reference = element.replaceChild(newChild,oldChild);
			返回值是一個指向已被替換的那個子節點的引用指標
	2). 該節點除了替換功能以外還有移動的功能.  
	3). 該方法只能完成單向替換, 若需要使用雙向替換, 需要自定義函式:
	/**
	 * 互換 aNode 和 bNode
	 * @param {Object} aNode
	 * @param {Object} bNode
	 */
	function replaceEach(aNode, bNode){
		
		if(aNode == bNode){
			return;
		}
		
		var aParentNode = aNode.parentNode;
		//若 aNode 有父節點
		if(aParentNode){
			var bParentNode = bNode.parentNode;
			
			//若 bNode 有父節點	
			if(bParentNode){
				var tempNode = aNode.cloneNode(true);
				bParentNode.replaceChild(tempNode, bNode);
				aParentNode.replaceChild(bNode, aNode);	
			}
		}

	}   
	
12. 插入節點:
	1). insertBefore(): 把一個給定節點插入到一個給定元素節點的給定子節點的前面
  			var reference =  element.insertBefore(newNode,targetNode);
         節點 newNode 將被插入到元素節點 element 中並出現在節點 targetNode 的前面. 節點 targetNode 必須是 element 元素的一個子節點。	 

    2). 自定義 insertAfter() 方法     
       /**
	 * 將 newChild 插入到 refChild 的後邊
	 * @param {Object} newChild
	 * @param {Object} refChild
	 */
	function insertAfter(newChild, refChild){
		var refParentNode = refChild.parentNode;
		
		//判斷 refChild 是否存在父節點
		if(refParentNode){
			//判斷 refChild 節點是否為其父節點的最後一個子節點
			if(refChild == refParentNode.lastChild){
				refParentNode.appendChild(newChild);
			}else{
				refParentNode.insertBefore(newChild, refChild.nextSibling);
			}	
		}
	}
    
    
13. 刪除節點:
	1). removeChild(): 從一個給定元素裡刪除一個子節點
   			var reference = element.removeChild(node);
		返回值是一個指向已被刪除的子節點的引用指標. 某個節點被 removeChild() 方法刪除時, 這個節點所包含的所有子節點將同時被刪除. 
		如果想刪除某個節點, 但不知道它的父節點是哪一個, parentNode 屬性可以幫忙。    
		
14. innerHTML屬性:
	1). 瀏覽器幾乎都支援該屬性, 但不是 DOM 標準的組成部分. innerHTML 屬性可以用來讀, 寫某給定元素裡的 HTML 內容	
	
15. 其它屬性, 參看 API: nsextSibling, 	previousSibling 等