返本求源——DOM元素的特性與屬性


拋磚引玉

  很多前端類庫(比如dojo與JQuery)在涉及dom操作時都會見到兩個模塊:attr、prop。某天代碼復查時,見到一段為某節點設置文本的代碼:

attr.set(node, 'innerText', 'Hello World!')

  這段代碼執行后並未生效,雖說innerText不是標准屬性,尚未被ff支持,可用的是chrome,這個屬性是被支持的。既然顯示的文本沒變,那就查看一下元素吧。

  innerText被添加到了html標簽上,而換成prop模塊后,成功的為節點替換文本。

  以上的這個小案例就涉及到了DOM操作時常常被忽略的一個問題:特性與屬性的區別

 

 

返本求源

    在DOM中,特性指的是html標簽上的屬性,比如:

  

  Property是對於某一類型特征的描述。可以這樣理解,在DOM元素中可以通過點語法訪問,又不是標准特性的都可以成為屬性。

  DOM中所有的節點都實現了Node接口。Node接口是在DOM1級中定義的,其中定義了一些用來描述DOM節點的屬性和操作方法。

  

  常見的nodeType、nodeValue、節點關系(parentNode、childNodes、firstChild、lastChild、previousSibling、nextSibling等)都屬於Node接口定義的屬性。對於Node接口的具體實現者,HTMLElement不僅繼承了這些屬性,還擁有五個wac規范中的五個標准特性:id、title、lang、dir、class和一個屬性:attributes。

   每一個元素都有一個或多個特性,這些特性的用途是給出相應元素或其內容的附加信息。通過DOM元素直接操作特性的的方法有三個:

  • getAttribute(attrName)
  • setAttribute(attrName, value)
  • removeAttribute(name)

  這三個方法都可以操作自定義特性。但是只有公認的(非自定義)特性才會以屬性的形式添加到DOM對象中,以屬性方式操作這些特性會被同步到html標簽中。HTMLElement的五個特性都有相應屬性與其對待:id、title、lang、dir、className。在DOM中以屬性方式操作這幾個特性會同步到html標簽中。

  不過,HTML5規范對自定義特性做了增強,只要自定義特性以"data-attrName"的形式寫入到html標簽中,在DOM屬性中就可以通過element.dataset.attrName的形式來訪問自定義特性,如:

<input type=​"text" name=​"as_q" class=​"box" id=​"searched_content" title=​"在此輸入搜索內容。" disabled=​"false" data-ff=​"fsdf">​
seh.dataset.ff

  

  元素的特性在DOM中以Attr類型來表示,Attr類型也實現了Node接口。Attr對象有三個屬性:name、value、specified。其中,name是特性的名稱,value是特性值,specified是一個布爾值,用來指示該特性是否被明確設置。

  document.createAttribute方法可以用來創建特性節點。例如,要為元素添加align特性可以使用如下方法:

ar attr = document.createAttribute('align')
attr.value = 'left'
seh.setAttributeNode(attr)

  要將新創建的特性添加到元素上,必須使用元素的setAttributeNode方法。添加特性后,特性會反映在html標簽上:

  注意,盡管特性節點也實現了Node接口,但特性卻不被認為是DOM文檔樹的一部分

 

  在所有的DOM節點中attributes屬性是Element類型所獨有的的屬性。從技術角度來說,特性就是存在於元素的attributes屬性中的節點。attributes屬性屬於NamedNodeMap類型的實例。元素的每一個特性節點都保存在NamedNodeMap對象中。NamedNodeMap類型擁有如下方法:

  • getNamedItem(name):返回特性名為name的特性節點
  • removeNamedItem(name):刪除特性名為name的特性節點
  • setNamedItem(attr):像元素中添加一個特性節點
  • item(pos):返回位於數組pos處的節點

  獲取、設置、刪除元素節點可以如下方式:

element.attributes.getNamedItem('align') //獲取

var attr = document.createAttribute('align');
attr.value = 'right';
element.attributes.setNamedItem(attr); //添加

element.attributes.removeNamedItem('align'); //刪除

  實際應用中並不建議使用特性節點的方式,而getAttribute、setAttribute、removeAttribute方法遠比操作特性節點更方便

  DOM、attributes、Attr三者關系應該這么畫:

 

 

應用總結

  基於以上DOM基礎知識和實際工作經驗,我將特性和屬性的區別聯系總結如下:

  1. 屬性以及公認特性可以通過點語法訪問;html5規范中,data-*形式的自定義特性可以通過element.dataset.*的形式來訪問,否則用getAttribute
  2. 特性值只能是字符串,而屬性值可以是任意JavaScript支持的類型
  3. 幾個特殊特性:
    1. style,通過getAttrbute和setAttribute來操作這個特性只能得到或設置字符串;而已屬性方式來操作就是在操作CSSStyleDeclaration對象
    2. 事件處理程序,通過特性方式得到和傳遞的都只是函數字符串;而已屬性方式操作的是函數對象
    3. value,對於支持value的元素,最好通過屬性方式操作,而且操作不會反映在html標簽上
      seh.value = 10
      <input type="text" name="as_q" class="box" id="searched_content" title="在此輸入搜索內容。" disabled="false" data-ff="fsdf" align="left">
    4. href,通過屬性方式設置可以反映到html標簽上,但用過點語法和getAttribute能夠取到的值並不一定相同
      <a href="/jsref/prop_checkbox_tabindex.asp" id="tabI">tabIndex</a>
      
      link.getAttribute('href') // "/jsref/prop_checkbox_tabindex.asp"
      
      link.href // "http://www.w3school.com.cn/jsref/prop_checkbox_tabindex.asp"
    5. disabled和checked,對於支持這兩個特性的元素來說,他們在html標簽中都是無狀態的,只要有獨立的標簽屬性在以點語法訪問時就返回true,如果html標簽屬性不存在,則以點語法訪問時就是false
    6. <input type=​"text" name=​"as_q" class=​"box" id=​"searched_content" title=​"在此輸入搜索內容。" disabled=​"false" data-ff=​"fsdf" align=​"left">​
      
      seh.disabled // true
      
      
      seh.disabled = false
      <input type=​"text" name=​"as_q" class=​"box" id=​"searched_content" title=​"在此輸入搜索內容。" data-ff=​"fsdf" align=​"left">​


      如果您覺得這篇文章對您有幫助,請不吝點擊右下方“推薦”,謝謝~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM