javascript --- javascript與DOM

javascript與DOM

咱們來個例子,一個HTML裏包含一段文本和一個無序的列表。javascript

<p id="intro">My first paragraph...</p>  
<ul>  
      <li>List item 1</li>  
      <li>List item 1</li>  
      <li>List item 1</li>  
      <li>List item 1</li>  
      <li>List item 1</li>  
</ul>  

上面例子裏,咱們使用getElementById DOM方法來訪問p段落。java

var pDom = document.getElementById('intro'); // 如今有了該DOM節點,這個DOM節點展現的是該信息段落

變量pDom如今已經引用到該DOM節點上了,咱們能夠對該節點作不少事情,好比查詢內容和屬性,或者其它任何操做,甚至能夠刪除它,克隆它,或者將它移到到DOM樹的其它節點上。node

文檔上的任何內容,咱們均可以使用JavaScript和DOM API來訪問,因此相似地,咱們也能夠訪問上面的無序列表,惟一的問題是該元素沒有ID屬性,若是ID的話就可使用相同的方式,或者使用以下getElementsByTagName方式:web

var allU = document.getElementsByTagName('ul');  // 'getElementsByTagName'返回的是一個節點集合 - 和數組有些相似

getElementsByTagName

getElementsByTagName方法返回的是一個節點集合,和數組相似也有length屬性,重要的一個特性是他是實時的——若是你在該元素裏添加一個新的li元素,這個集合就會自動更新,介於他和數組類型,因此能夠和訪問數組同樣的方法來訪問,因此從0開始:數組

// 訪問無序列表: [0]索引
var unorderedList = document.getElementsByTagName('ul')[0];
// 獲取全部的li集合:  
var allListItems = unorderedList.getElementsByTagName('li');
// 循環遍歷
for (var i = 0, length = allListItems.length; i < length; i++) {
    // 彈出該節點的text內容
    alert(allListItems[i].firstChild.data);
} 

如下圖例更清晰地展現了DOM獲取的知識:瀏覽器

DOM穿梭

「穿梭」這個詞主要是用來描述經過DOM查找節點,DOM API提供了大量的節點屬性讓咱們來往上或者往下查詢節點。app

全部的節點都有這些屬性,都是能夠用於訪問相關的node節點:函數

  1. Node.childNodes: 訪問一個單元素下全部的直接子節點元素,能夠是一個可循環的類數組對象。該節點集合能夠保護不一樣的類型的子節點(好比text節點或其餘元素節點)。
  2. Node.firstChild: 與‘childNodes’數組的第一個項(‘Element.childNodes[0]‘)是一樣的效果,僅僅是快捷方式。
  3. Node.lastChild: 與‘childNodes’數組的最後一個項(‘Element.childNodes[Element.childNodes.length-1]‘)是一樣的效果,僅僅是快捷方式。shortcut.
  4. Node.parentNode: 訪問當前節點的父節點,父節點只能有一個,祖節點能夠用‘Node.parentNode.parentNode’的形式來訪問。
  5. Node.nextSibling: 訪問DOM樹上與當前節點同級別的下一個節點。
  6. Node.previousSibling: 訪問DOM樹上與當前節點同級別的上一個節點。

經過這張圖,理解起來就簡單多了,但有個很是重要的知識點:那就是元素之間不能有空格,若是ul和li之間有空格的話,就會被認爲是內容爲空的text node節點,這樣ul.childNodes[0]就不是第一個li元素了。相應地,<p>的下一個節點也不是<ul>,由於<p>和<ul>之間有一個空行的節點,通常遇到這種狀況須要遍歷全部的子節點而後判斷nodeType類型,1是元素,2是屬性,3是text節點,詳細的type類型能夠經過此地址google

    Node.ELEMENT_NODE == 1
    Node.ATTRIBUTE_NODE == 2
    Node.TEXT_NODE == 3
    Node.CDATA_SECTION_NODE == 4
    Node.ENTITY_REFERENCE_NODE == 5
    Node.ENTITY_NODE == 6
    Node.PROCESSING_INSTRUCTION_NODE == 7
    Node.COMMENT_NODE == 8
    Node.DOCUMENT_NODE == 9
    Node.DOCUMENT_TYPE_NODE == 10
    Node.DOCUMENT_FRAGMENT_NODE == 11
    Node.NOTATION_NODE == 12

操做元素

每一個DOM節點都包括一個屬性集合,大多數的屬性都提供爲相應的功能提供了抽象。例如,若是有一個帶有ID屬性intro的文本元素,你能夠很容易地經過DOM API來改變該元素的顏色:spa

document.getElementById('intro').style.color = '#FF0000';

爲了理解這個API的功能,咱們一步一步分開來看就很是容易理解了:

var myDocument = document;  
var myIntro = myDocument.getElementById('intro');  
var myIntroStyles = myIntro.style;  
  
// 如今,咱們能夠設置顏色了:  
myIntroStyles.color = '#FF0000';

如今,咱們有了該文本的style對象的引用了,因此咱們能夠添加其它的CSS樣式:

myIntroStyles.padding = '2px 3px 0 3px';  
myIntroStyles.backgroundColor = '#FFF';  
myIntroStyles.marginTop = '20px'; 

這裏咱們只是要了基本的CSS屬性名稱,惟一區別是CSS屬性的名稱若是帶有-的話,就須要去除,好比用marginTop代替margin-top。例如,下面的代碼是不工做的,而且會拋出語法錯誤:

myIntroStyles.padding-top = '10em';       
// 產生語法錯誤:
// 在JavaScript裏橫線-是減法操做符
// 並且也沒有這樣的屬性名稱

屬性能夠像數組同樣訪問,因此利用這個知識咱們能夠建立一個函數來改變任何給定元素的樣式:

function changeStyle(elem, property, val) {
    elem.style[property] = val; // 使用[]來訪問屬性
}

// 使用上述的函數:  
var myIntro = document.getElementById('intro'); // 獲取intro文本對象
changeStyle(myIntro, 'color', 'red');  

一般DOM操做都是改變原始的內容,這裏有幾種方式來實現這個,最簡單的是使用innerHTML屬性,例如:

var myIntro = document.getElementById('intro');  
  
// 替換當前的內容
myIntro.innerHTML = 'New content for the <strong>amazing</strong> paragraph!';  
  
// 添加內容到當前的內容裏 
myIntro.innerHTML += '... some more content...';

惟一的問題是該方法沒在規範裏定義,並且在DOM規範裏也沒有定義,若是你不反感的話請繼續使用,由於它比咱們下面要討論其它的方法快多了。

Node節點

var myIntro = document.getElementById('intro');  
  
// 添加內容
var someText = 'This is the text I want to add';  
var textNode = document.createTextNode(someText);  
myIntro.appendChild(textNode);

這裏咱們使用了appendChild方法將新text節點附件到文本字段,這樣作比非標準的innerHTML方法顯得有點長,但瞭解這些原理依然很重要,這裏有一個使用DOM方法的更詳細例子:

var myIntro = document.getElementById('intro');  
  
// 添加新鏈接到文本節點
// 首先,建立新鏈接元素
var myNewLink = document.createElement('a'); // <a/>  
myNewLink.href = 'http://google.com'; // <a href="http://google.com"/>  
myNewLink.appendChild(document.createTextNode('Visit Google')); 
// <a href="http://google.com">Visit Google</a>  
  
// 將內容附件到文本節點
myIntro.appendChild(myNewLink);

另外DOM裏還有一個insertBefore方法用於再節點前面附件內容,經過insertBefore和appendChild咱們能夠實現本身的insertAfter函數:

// 'Target'是DOM裏已經存在的元素
// 'Bullet'是要插入的新元素
  
function insertAfter(target, bullet) {  
    target.nextSibling ?  
        target.parentNode.insertBefore(bullet, target.nextSibling)  
        : target.parentNode.appendChild(bullet);  
}  
  
// 使用了3目表達式:  
// 格式:條件?條件爲true時的表達式:條件爲false時的表達式

上面的函數首先檢查target元素的同級下一個節點是否存在,若是存在就在該節點前面添加bullet節點,若是不存在,就說明target是最後一個節點了,直接在後面append新節點就能夠了。DOM API沒有給提供insertAfter是由於真的不必了——咱們能夠本身建立。

DOM操做有不少內容,上面你看到的只是其中一部分。

Event事件

瀏覽器事件是全部web程序的核心,經過這些事件咱們定義將要發生的行爲,若是在頁面裏有個按鈕,那點擊此按鈕以前你須要驗證表單是否合法,這時候就可使用click事件,下面列出的最標準的事件列表:

注:正如咱們上章所說的,DOM和JavaScript語言是2個單獨的東西,瀏覽器事件是DOM API的一部分,而不是JavaScript的一部分。

鼠標事件

  1.  ‘mousedown’ – 鼠標設備按下一個元素的時候觸發mousedown事件。
  2.  ‘mouseup’ – 鼠標設備從按下的元素上彈起的時候觸發mouseup事件。
  3.  ‘click’ – 鼠標點擊元素的時候觸發click事件。
  4.  ‘dblclick’ – 鼠標雙擊元素的時候觸發dblclick事件。
  5. mouseover’ – 鼠標移動到某元素上的時候觸發mouseover事件。
  6.  ‘mouseout’ – 鼠標從某元素離開的時候觸發mouseout事件。
  7.  ‘mousemove’ – 鼠標在某元素上移動但未離開的時候觸發mousemove事件。

鍵盤事件

  1. keypress’ – 按鍵按下的時候觸發該事件。
  2. keydown’ – 按鍵按下的時候觸發該事件,而且在keypress事件以前。
  3. keyup’ – 按鍵鬆開的時候觸發該事件,在keydown和keypress事件以後。

表單事件

  1. select’ – 文本字段(input, textarea等)的文本被選擇的時候觸發該事件。
  2. change’ – 控件失去input焦點的時候觸發該事件(或者值被改變的時候)。
  3. submit’ – 表單提交的時候觸發該事件。
  4. reset’ – 表單重置的時候觸發該事件。
  5. focus’ – 元素得到焦點的時候觸發該事件,一般來自鼠標設備或Tab導航。
  6. blur’ – 元素失去焦點的時候觸發該事件,一般來自鼠標設備或Tab導航。

其它事件

  1. load’ – 頁面加載完畢(包括內容、圖片、frame、object)的時候觸發該事件。
  2. resize’ – 頁面大小改變的時候觸發該事件(例如瀏覽器縮放)。
  3. scroll’ – 頁面滾動的時候觸發該事件。
  4. unload’ – 從頁面或frame刪除全部內容的時候觸發該事件(例如離開一個頁面)。
相關文章
相關標籤/搜索