[javascript]Traversing the DOM

整理 Treehouse 前端課程中 JavaScript and the DOM 的最後一節 Traversing the DOM 內容。

DOM Traversal 的意思是,可以透過一個 element 與這個 element 的關係去選取其他的 element。


parentNode

  • parentNode:顧名思義,選取被選取的 element 的 parent node。
// 選取 id 為 myParagraph 的 node
let paragraph = document.getElementbyId('myParagraph'); 

// 使用 paragraph 選取它的 parent node
let parent = paragraph.parenNode; 

// 可以直接利用這個 parent node 做些事
parent.removeChild(paragraph); // 刪除 paragraph node

previousElementSibling & insertBefore

  • previousElementSibling:選取被選取的 element 前一個的 sibling。
  • insertBefore:將被選取的 element 插入在某一個 element 之前, let insertedNode = parentNode.insertBefore(newNode, referenceNode)

previousSibling v.s. previousSibling

為什麼 sibling 要特別加上 ‘Element’ 呢?因為如果使用 previousSibling 他會抓取前一個 sibling node,不管它是什麼。而我們前一篇講過, node 包含 document、element、attribute 和 text。所以使用 previousElementSibling 我們就只會抓前面的 element sibling。

在課程的範例中,現在想要按了 Up 按鈕之後,該

  • 就會上移。

    <ul>
      <li>grapes 
        <button class="up">Up</button>
        <button class="remove">Remove</button>
      </li>
      <li>amethyst 
        <button class="up">Up</button>
        <button class="remove">Remove</button>
      </li>
      <li>lavender 
        <button class="up">Up</button>
        <button class="remove">Remove</button>
      </li>
      <li>plums 
        <button class="up">Up</button>
        <button class="remove">Remove</button>
      </li>
    </ul>
    // 選取 ul 的 tag
    const listDiv = document.querySelector('.list');
    const listUl = listDiv.querySelector('ul');
    
    // 按下 up 按鈕之後,該 li tag 會往上移
    listUl.addEventListener('click', (event) => {
      if(event.target.className == 'up') {
      	// 被 click 的 button 的 parent node 就是 li
        let li = event.target.parentNode; 
        // 被選取的 li tag 的 previous element sibiling,也就是前一個 li tag
        let prevLi = li.previousElementSibling; 
        // 這個 li 的 parent node
        let ul = li.parentNode; 
        // 如果 prevLi 不是 null,換句話說,不是第一個
        if (prevLi) {
          // 將被選取的 li tag 往前移
          ul.insertBefore(li, prevLi); 
        }
      }
    });

    nextElementSibling & insertBefore

    按了 down button 之後,該 li 往下移。基本上概念和剛剛上面往前一是一樣的,只是現在使用 nextElementSibling,去選取後面的 element。

    <ul>
      <li>grapes 
        <button class="up">Up</button>
        <button class="down">Down</button>
        <button class="remove">Remove</button>
      </li>
      <li>amethyst 
        <button class="up">Up</button>
        <button class="down">Down</button>
        <button class="remove">Remove</button>
      </li>
      <li>lavender 
        <button class="up">Up</button>
        <button class="down">Down</button>
        <button class="remove">Remove</button>
      </li>
      <li>plums 
        <button class="up">Up</button>
        <button class="down">Down</button>
        <button class="remove">Remove</button>
      </li>
    </ul>
    // 選取 ul 的 tag
    const listDiv = document.querySelector('.list');
    const listUl = listDiv.querySelector('ul');
    
    // 按下 up 按鈕之後,該 li tag 會往上移
    listUl.addEventListener('click', (event) => {
      if(event.target.className == 'down') {
        let li = event.target.parentNode;
        let nextLi = li.nextElementSibling;
        let ul = li.parentNode;
        if (nextLi) {
          ul.insertBefore(nextLi, li);
        }    
      }
    });

    children

    .children 可以選取該 element 底下所有的 child element。

    const listDiv = document.querySelector('.list');
    const listUl = listDiv.querySelector('ul');
    
    // lisUl 底下的 child,也就是 li tag
    const lis = listUl.children;

    firstChild & lastChild v.s. firstElementChild & lastElementChild

    選取該 element 的第一個或最後一個 child。同樣的,firstElementChild & lastElementChild 選取的會是 element。