為啥要使用節點操作
主要是根據節點之間的關系來更方便的獲取元素對象.
例如: 之前寫過的點擊計數示例, 前面的做法是使用 獲取兩個 input 標簽, 再進行操作.
但是兩個 input 標簽其實是兄弟關系, 咱們可以借助節點操作, 更方便的獲取到 input 的元素對象.
?<script> ? ?var text = document.querySelector('#text'); ? ?var btn = document.querySelector('#btn'); ? ?btn.onclick = function () { ? ? ? ?var num = +text.value; ? ? ? ?console.log(num); ? ? ? ?num++; ? ? ? ?text.value = num; ? }script>
核心關系: 父子, 兄弟.
頁面中的一切內容都是節點
文本, 元素, 屬性等都是節點.
每個節點對象主要有三個屬性:
?div><script> ? ?var div = document.querySelector('.box'); ? ?console.dir(div);script>
獲取父節點
體會 HTML 中的父子關系
? ? ? ? ? ? ?父子關系title>head> ? ? ? ? ? ? ? ? ? ? ? ?div> ? ? ? ?div> ? ?div>body>html>
在這個 html 中:
使用 屬性獲取到該節點的父節點.
? ? ? ? ? ? ?div> ? ?div>div><script> ? ?var son = document.querySelector('.son'); ? ?console.log(son); ? ?console.log(son.parentNode); ? ?console.log(son.parentNode.parentNode);script>
獲取所有子節點
1) 使用 屬性獲取到該節點的子節點
? ? ?- 1li> ? ?
- 2li> ? ?
- 3li>ul><script> ? ?var ul = document.querySelector('ul'); ? ?console.log(ul.childNodes);script>
注意! 結果是 類型, 得到的是 "節點", 而不是 "元素" (節點的范圍比元素更廣)
第一個 li 和 ul 之間存在換行.
最后一個 li 和 ul 之間存在換行.
li 和 li 之間也存在換行.
這些換行也都是節點(文本節點).
如果想只獲取元素節點, 可以手動寫個函數, 把 type 為 1 的節點保留下來.
js">?function getElementNode(nodeList) { ? ?var result = []; ? ?for (var i = 0; i < nodeList.length; i++) { ? ? ? ?if (nodeList[i].nodeType == 1) { ? ? ? ? ? ?result.push(nodeList[i]); ? ? ? } ? } ? ?return result;}console.log(getElementNode(ul.childNodes));
當然, 這樣做比較麻煩.
2) 使用 屬性獲取子節點中的元素節點(非標準, 但是各個瀏覽器都支持)
? ? ?- 1li> ? ?
- 2li> ? ?
- 3li>ul><script> ? ?var ul = document.querySelector('ul'); ? ?console.log(ul.children);script>
屬性得到的是一個 , 只包含元素對象.
獲取第一個節點/最后一個節點
? ? ?- 1li> ? ?
- 2li> ? ?
- 3li> ? ?
- 4li>ul><script> ? ?var ul = document.querySelector('ul'); ? ?console.log(ul.firstChild); ? ?console.log(ul.lastChild); ? ?console.log(ul.firstElementChild); ? ?console.log(ul.lastElementChild);script>
實際開發更常用的辦法是直接借助 得到子元素數組, 然后通過下標來操作.
?ul.children[0]; ? ? ? ? ? ? // 第一個節點ul.children[ul.length - 1]; // 最后一個節點
獲取兄弟節點
? ? ?11div> ? ?22div>div><script> ? ?var child1 = document.querySelector('.child1'); ? ?console.log(child1.nextSibling); ? ?console.log(child1.previousSibling); ? ?console.log(child1.nextElementSibling); ? ?console.log(child1.previousElementSibling);script>
單詞本意就是 兄;弟;姐;妹;
新增節點
分成兩個步驟
創建元素節點
把元素節點插入到 dom 樹中.
第一步相當于生了個娃, 第二步相當于給娃上戶口.
1. 創建元素節點
使用 方法來創建一個元素. 參數暫不關注.
?var element = document.createElement(tagName[, options]);
代碼示例:
?div><script> ? ?var div = document.createElement('div'); ? ?div.id = 'mydiv'; ? ?div.className = 'box'; div.innerHTML = 'hehe'; ? ?console.log(div);script>
此時發現, 雖然創建出新的 div 了, 但是 div 并沒有顯示在頁面上. 這是因為新創建的節點并沒有加入到 DOM 樹中.
上面介紹的只是創建元素節點, 還可以使用:
我們以 為主即可.
2. 插入節點到 dom 樹中
1) 使用 將節點插入到指定節點的最后一個孩子之后
?element.appendChild(aChild)
?div><script> ? ?var div = document.createElement('div'); ? ?div.id = 'mydiv'; ? ?div.className = 'box'; ? ?div.innerHTML = 'hehe'; ? ?var container = document.querySelector('.container'); ? ?container.appendChild(div);script>
2) 使用 將節點插入到指定節點之前.
?var insertedNode = parentNode.insertBefore(newNode, referenceNode);
如果 為 null 則 將被插入到子節點的末尾.
注意: 引用節點不是可選參數.
? ? ?11div> ? ?22div> ? ?33div> ? ?44div>div><script> ? ?var newDiv = document.createElement('div'); ? ?newDiv.innerHTML = '我是新的節點'; ? ?var container = document.querySelector('.container'); ? ?console.log(container.children); ? ?container.insertBefore(newDiv, container.children[0]);script>
注意1: 如果針對一個節點插入兩次, 則只有最后一次生效(相當于把元素移動了)
? ? ?11div> ? ?22div> ? ?33div> ? ?44div>div><script> ? ?var newDiv = document.createElement('div'); ? ?newDiv.innerHTML = '我是新的節點'; ? ?var container = document.querySelector('.container'); ? ?console.log(container.children); ? ?// 此處的 children 里有 4 個元素 ? ?container.insertBefore(newDiv, container.children[0]); ? ?// 此處的 children 里有 5 個元素(上面新插了一個), 0 號元素是 新節點, ? ?// 1 號元素是 11, 2號節點是 22, 所以是插入到 22 之前. ? ?container.insertBefore(newDiv, container.children[2]);script>
注意2: 一旦一個節點插入完畢, 再針對剛剛的節點對象進行修改, 能夠同步影響到 DOM 樹中的內容.
? ? ?11div> ? ?22div> ? ?33div> ? ?44div>div><script> ? ?var newDiv = document.createElement('div'); ? ?newDiv.innerHTML = '我是新的節點'; ? ?var container = document.querySelector('.container'); ? ?console.log(container.children); ? ?container.insertBefore(newDiv, container.children[0]); ? ? ? ?// 插入完畢后再次修改 newDiv 的內容 ? ?newDiv.innerHTML = '我是新節點2';script>
代碼示例: 待辦事項
功能:
界面上包含一個輸入框和新增任務按鈕. 點擊新增則把輸入框中的任務加入到任務列表中.
任務列表中顯示當前待辦的所有任務.
每個任務前面包含一個復選框, 勾選則表示任務完成, 任務自動被放到另外一個已完成列表.
a) 頁面布局
? ? ? ? ? ? ?未完成h3> ? ? ? ? ? ?div> ? ? ? ? ? ?已完成h3> ? ?div>div>