節(jié)點(diǎn)操作

2018-07-10 14:37 更新

Table of Contents generated with DocToc

節(jié)點(diǎn)操作

因?yàn)?DOM 的存在,這使我們可以通過 JavaScript 來獲取、創(chuàng)建、修改、或刪除節(jié)點(diǎn)。

NOTE:下面提供的例子中的 element 均為元素節(jié)點(diǎn)。

獲取節(jié)點(diǎn)

父子關(guān)系

  • element.parentNode
  • element.firstChild/element.lastChild
  • element.childNodes/element.children

兄弟關(guān)系

  • element.previousSibling/element.nextSibling
  • element.previousElementSibling/element.nextElementSibling

通過節(jié)點(diǎn)直接的關(guān)系獲取節(jié)點(diǎn)會導(dǎo)致代碼維護(hù)性大大降低(節(jié)點(diǎn)之間的關(guān)系變化會直接影響到獲取節(jié)點(diǎn)),而通過接口則可以有效的解決此問題。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>ELEMENT_NODE & TEXT_NODE</title>
</head>
<body>
  <ul id="ul">
    <li>First</li>
    <li>Second</li>
    <li>Third</li>
    <li>Fourth</li>
  </ul>
  <p>Hello</p>
  <script type="text/javascript">
    var ulNode = document.getElementsByTagName("ul")[0];
    console.log(ulNode.parentNode);             //<body></body>
    console.log(ulNode.previousElementSibling); //null
    console.log(ulNode.nextElementSibling);     //<p>Hello</p>
    console.log(ulNode.firstElementChild);      //<li>First</li>
    console.log(ulNode.lastElementChild);       //<li>Fourth</li>
  </script>
</body>
</html>

NTOE:細(xì)心地人會發(fā)現(xiàn),在節(jié)點(diǎn)遍歷的例子中,body、ul、li、p節(jié)點(diǎn)之間是沒有空格的,因?yàn)槿绻锌崭?,那么空格就會被?dāng)做一個TEXT節(jié)點(diǎn),從而用ulNode.previousSibling獲取到得就是一個空的文本節(jié)點(diǎn),而不是 <li>First</li> 節(jié)點(diǎn)了。即節(jié)點(diǎn)遍歷的幾個屬性會得到所有的節(jié)點(diǎn)類型,而元素遍歷只會得到相對應(yīng)的元素節(jié)點(diǎn)。一般情況下,用得比較多得還是元素節(jié)點(diǎn)的遍歷屬性。

實(shí)現(xiàn)瀏覽器兼容版的element.children

有一些低版本的瀏覽器并不支持 element.children 方法,但我們可以用下面的方式來實(shí)現(xiàn)兼容。

<html lang>
<head>
  <meta charest="utf-8">
  <title>Compatible Children Method</title>
</head>
<body id="body">
  <div id="item">
    <div>123</div>
    <p>ppp</p>
    <h1>h1</h1>
  </div>
  <script type="text/javascript">
    function getElementChildren(e){
      if(e.children){
        return e.children;
      }else{
        /* compatible other browse */
        var i, len, children = [];
        var child = element.firstChild;
        if(child != element.lastChild){
          while(child != null){
            if(child.nodeType == 1){
              children.push(child);
            }
            child = child.nextSibling;
          }
        }else{
          children.push(child);
        }
        return children;
      }
    }
    /* Test method getElementChildren(e) */
    var item = document.getElementById("item");
    var children = getElementChildren(item);
    for(var i =0; i < children.length; i++){
      alert(children[i]);
    }
  </script>
</body>
</html>

NOTE:此兼容方法為初稿,還未進(jìn)行兼容性測試。

接口獲取元素節(jié)點(diǎn)

  • getElementById
  • getElementsByTagName
  • getElementsByClassName
  • querySelector
  • querySelectorAll
API只作用于 document唯一返回值live
getElementById
getElementsByTagName
getElementsByClassName
querySelectorAll
querySelector
getElementById

獲取文檔中指定 id 的節(jié)點(diǎn)對象。

var element = document.getElementById('id');
getElementsByTagName

動態(tài)的獲取具有指定標(biāo)簽元素節(jié)點(diǎn)的集合(其返回值會被 DOM 的變化所影響,其值會發(fā)生變化)。此接口可直接通過元素而獲取,不必直接作用于 document 之上。

// 示例
var collection = element.getElementsByTagName('tagName');

// 獲取指定元素的所有節(jié)點(diǎn)
var allNodes = document.getElementsByTagName('*');

// 獲取所有 p 元素的節(jié)點(diǎn)
var elements = document.getElementsByTagName('p');
// 取出第一個 p 元素
var p = elements[0];
getElementsByClassName

獲取指定元素中具有指定 class 的所有節(jié)點(diǎn)。多個 class 可的選擇可使用空格分隔,與順序無關(guān)。

var elements = element.getElementsByClassName('className');

NOTE:IE9 及一下版本不支持 getElementsByClassName

兼容方法

function getElementsByClassName(root, className) {
  // 特性偵測
  if (root.getElementsByClassName) {
    // 優(yōu)先使用 W3C 規(guī)范接口
    return root.getElementsByClassName(className);
  } else {
    // 獲取所有后代節(jié)點(diǎn)
    var elements = root.getElementsByTagName('*');
    var result = [];
    var element = null;
    var classNameStr = null;
    var flag = null;

    className = className.split(' ');

    // 選擇包含 class 的元素
    for (var i = 0, element; element = elements[i]; i++) {
      classNameStr = ' ' + element.getAttribute('class') + ' ';
      flag = true;
      for (var j = 0, name; name = className[j]; j++) {
        if (classNameStr.indexOf(' ' + name + ' ') === -1) {
          flag = false;
          break;
        }
      }
      if (flag) {
        result.push(element);
      }
    }
    return result;
  }
}
querySelector / querySelectorAll

獲取一個 list (其返回結(jié)果不會被之后 DOM 的修改所影響,獲取后不會再變化)符合傳入的 CSS 選擇器的第一個元素或全部元素。

var listElementNode = element.querySelector('selector');
var listElementsNodes = element.querySelectorAll('selector');

var sampleSingleNode = element.querySelector('#className');
var sampleAllNodes = element.querySelectorAll('#className');

NOTE: IE9 一下不支持 querySelector 與 querySelectorAll

創(chuàng)建節(jié)點(diǎn)

創(chuàng)建節(jié)點(diǎn) -> 設(shè)置屬性 -> 插入節(jié)點(diǎn)

var element = document.createElement('tagName');

修改節(jié)點(diǎn)

textContent

獲取或設(shè)置節(jié)點(diǎn)以及其后代節(jié)點(diǎn)的文本內(nèi)容(對于節(jié)點(diǎn)中的所有文本內(nèi)容)。

element.textContent; // 獲取
element.textContent = 'New Content';

NOTE:不支持 IE 9 及其一下版本。

innerText (不符合 W3C 規(guī)范)

獲取或設(shè)置節(jié)點(diǎn)以及節(jié)點(diǎn)后代的文本內(nèi)容。其作用于 textContent 幾乎一致。

element.innerText;

NOTE:不符合 W3C 規(guī)范,不支持 FireFox 瀏覽器。

FireFox 兼容方案

if (!('innerText' in document.body)) {
  HTMLElement.prototype.__defineGetter__('innerText', function(){
    return this.textContent;
  });
  HTMLElement.prototype.__defineSetter__('innerText', function(s) {
    return this.textContent = s;
  });
}

插入節(jié)點(diǎn)

appendChild

在指定的元素內(nèi)追加一個元素節(jié)點(diǎn)。

var aChild = element.appendChild(aChild);

insertBefore

在指定元素的指定節(jié)點(diǎn)前插入指定的元素。

var aChild = element.insertBefore(aChild, referenceChild);

刪除節(jié)點(diǎn)

刪除指定的節(jié)點(diǎn)的子元素節(jié)點(diǎn)。

var child = element.removeChild(child);

innerHTML

獲取或設(shè)置指定節(jié)點(diǎn)之中所有的 HTML 內(nèi)容。替換之前內(nèi)部所有的內(nèi)容并創(chuàng)建全新的一批節(jié)點(diǎn)(去除之前添加的事件樣式)。innerHTML 不檢查內(nèi)容,直接運(yùn)行并替換原先的內(nèi)容。

NOTE:只建議在創(chuàng)建全新的節(jié)點(diǎn)時使用。不可在用戶可控的情況下使用。

var elementsHTML = element.innerHTML;

存在的問題

  • 低版本 IE 存在內(nèi)存泄露
  • 安全問題(用戶可以在名稱中運(yùn)行腳本代碼)


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號