JS高階程式設計第十一章.個人學習筆記

賴嘉豪發表於2018-10-25

1.document.querySelector()方法:

接受一個CSS選擇符 返回與該模式匹配的第一個元素 如果沒有 則返回null

2.document.querySelectorAll()方法:

接受一個CSS選擇符 返回與該模式匹配的NodeList的例項. 如果沒有 則返回空陣列

3.matchesSelector()方法:

接受一個CSS選擇符 如果呼叫的元素與該選擇符匹配,則返回true 否則返回false 相容問題查詢288頁。


元素遍歷:

對於元素之間的空格,IE9之前不會返回文字節點,但其他所有瀏覽器都會返回文字節點。

因此導致了在使用childNodes和firstChild等屬性時的行為不一致。

也為此介紹幾個能處理這個問題的API:

childElementCount:返回子元素(不包括文字節點和註釋)的個數。

firstElementChild:指向第一個子元素;firstChild的元素版。

lastElementChild:指向最後一個子元素;lastChild的元素版。

PreviousElementSibling:指向前一個同輩元素;previousSibling的元素版。

nextElementSibling:指向後一個同輩元素;nextSibling的元素版。


classList屬性(chrome  Firefox 3.6+支援)

有length屬性 去的每個元素可以用item()方法 也可以用方括號語法;

此外 還有以下方法:

add(value):將給定的字串值新增到列表中。如果值已經存在,就不新增了。

contains(value):表示列表中是否存在給定的值,如果存在則返回true,否則返回false。

remove(value):從列表刪除給定的字串。

toggle(value):如果列表中存在給定的值 則刪除 如果不存在 則新增



HTML5新增焦點管理功能:

document.activeElement屬性:這個屬性始終引用DOM中當前獲得了焦點的元素。

元素獲得焦點的方式有載入、使用者輸入(通常是通過按Tab鍵) 和在程式碼中呼叫focus()方法

例如:

var button = document.getElementById("myButton");
button.focus();
alert(document.activeElement === button); //true

複製程式碼

預設情況下,

文件剛剛載入完成時,document.activeElement中儲存的是document.body元素的引用。

文件載入期間,document.activeElement的值為null


還新增了document.hasFocus()方法,這個方法用於確定文件是否獲得了焦點。

var button =document.getElementById('myButton');
button.focus();
alert(document.hasFocus());//true

複製程式碼


-----------------------------------------------------------

HTMLDocument的變化

HTML5擴充了HTMLDocument,增加了新的功能。與HTML5中新增的其他DOM擴充類似,這些變化同樣基於那些已經得到很多瀏覽器完美支援的專有擴充。所以,儘管這些擴充被寫入標準的時間相對不長,但很多瀏覽器很早就已經支援這些功能了。

1.readyState 屬性

Document的readyState屬性有兩個可能的值:
loading,正在載入文件;
complete,已經載入完文件。

使用document.readyState的最恰當方式,就是通過它來實現一個指示文件已經載入完成的指示器。在這個屬性得到廣泛支援之前,要實現這樣一個指示器,必須藉助onload事件處理程式設定一個標籤,表明文件已經載入完畢。


document.readyState屬性的基本用法如下:

if(document.readyState == 'complete'){
    //執行操作
}
複製程式碼


2.相容模式

從IE6開始區分渲染頁面的模式是標準的還是混雜的,檢測頁面的相容模式就成為瀏覽器的必要功能。

document有個屬性compatMode,就是為了告訴開發人員瀏覽器採用了哪種渲染模式。

標準模式下document.compatMode的值等於Css1Compat

混雜模式下document.compatMode的值等於BackCompat



3.head屬性

document.body引用文件的<body>元素。

html5新增document.head引用文件的<head>元素。(Chrome和Safari5相容)

不相容的話用getElementsByTagName()方法。




重點:自定義資料屬性

HTML5規定可以為元素新增非標準的屬性,但是要新增字首data-,目的是為元素提供與渲染無關的資訊,或者提供語義資訊。這些屬性任意新增、隨便命名,只要奕data-開頭即可。

例如該標籤:

<div id='myDiv' data-appId='12345' data-myname='nunu'></div>

新增了自定義屬性之後,可以通過元素的dataset屬性來訪問自定義屬性的值。dataset屬性的值是DOMStringMap的一個例項,也就是一個名值對兒的對映。在這個對映中,每個

data-name形式的屬性都會有一個對應的屬性,只不過屬性名沒有data-字首,比如在上面的例子中,自定義屬性data-myname對映對應的屬性是myname。

支援該屬性的瀏覽器有Firefox 6+ 和Chrome




插入標記

1.innerHTML屬性

在讀模式下,innerHTML屬性返回與呼叫元素的所有子節點(包括元素、註釋和文字節點)對應的HTML標記。

在寫模式下,innerHTML會根據指定的值建立新的DOM樹,然後用這個DOM樹完全替換呼叫元素原先的所有子節點。例如:

<div id='content'>
    <p>aaa<strong>bbb</strong>ccc</p>
    <ul>
        <li>ddd</li>
        <li>ddd</li>
    </ul>
</div>
複製程式碼

對於上面的div元素來說 他的innerHTML屬性會返回如下字串。

<p>aaa<strong>bbb</strong>ccc</p>
<ul>
    <li>ddd</li>
    <li>ddd</li>
</ul>複製程式碼

但是,不同瀏覽器返回的文字格式會有所不同。

在寫模式下,innerHTML的值會被解析為DOM子樹,替換呼叫元素原來的所有子節點。因為它的值被認為是HTML,所以其中的所有標籤都會按照瀏覽器處理 HTML的標準方式替換為元素(轉換結果因瀏覽器而異)。如果設定的值是文字而沒有HTML標籤 則會被設定成純文字(與innerText的在寫模式輸出一樣)。


提前解釋一個概念:‘無作用域的元素’= 頁面中看不到的元素。類似於style元素和註釋。

script元素也被認為是‘無作用域的元素’。

如果通過innerHTML插入的字串開頭就是一個無作用域的元素,那麼IT會在解析這個字串之前先刪除該元素。

也就是說 如果要用innerHTML插入一段指令碼script

需要用類似下面這幾種方法:

1.開頭新增一個可以被看見的元素(新增之後為了頁面美觀可能得移除這個文字)

div.innerHTML = '_<script defer>alert('hi');<\/script>';

div.innerHTML = '<div>&nbsp;</div><script defer>alert('hi');<\/script>'

div.innerHTML = '<input type=\"hidden\"><script defer>alert('hi');<\/script>'

關於插入style元素 大多數瀏覽器都是支援直接插入的,

但是IE8及更早的版本中,<style>也是一個沒有作用域的元素,因此也可以用上面的第一種方法前置一個有作用域的元素解決該相容問題。

有一部分元素不支援innerHTML屬性。如:<col><colgroup><frameset><head><html><style><table><tbody><thead><tfoot><tr>.

在IE8及更早的版本中,<title>元素也沒有innerHTML屬性


為了更可靠的方式處理HTML。

IE8提供了window.toStaticHTML()方法,這個方法接收一個引數,即一個HTML字串;返回一個經過無害處理後的版本---從源HTML中刪除所有指令碼節點和事件處理程式屬性。比如:

var text = '<a href = \" #\" onclick = \"alert('hi')\">Click me</a>";
var sanitized = window.toStaticHTML(text);   //IE8 only
alert(sanitized);    //'<a href=\"#\">Click Me</a>' 複製程式碼

這個例子將一個HTML連結字串傳給了toStaticHTML()方法,得到的無害版本中去掉了onclick事件屬性。只有IE8原生支援這個方法,

2.outerHTML屬性

在讀模式下,outerHTML返回撥用它的元素及所有子節點的HTML標籤。

在寫模式下,outerHTML會根據指定的HTML字串建立新的DOM子樹,然後用這個DOM子樹完全替換呼叫元素。

<div id='content'>
    <p>aaa<strong>bbb</strong>ccc</p>
    <ul>
        <li>ddd</li>
        <li>ddd</li>
    </ul>
</div>複製程式碼

如果在DIV元素上呼叫outerHTML,會返回與上面相同的程式碼,包括<div>本身。不過,由於瀏覽器解析和解釋HTML標記的不同,結果也可能會有所不同(這裡的不同於使用innerHTML屬性時存在的差異性質是一樣的。)

使用outerHTML屬性以下面這種方式設定值:

div.outerHTML = "<p>aaaaaaaaa</p>";複製程式碼

這行程式碼的操作與下面這些DOM指令碼程式碼一樣:

var  p = document.createElement('p');
p.appendChild(document.createTextNode('aaaaaaaaa'));
div.parentNode.replaceChild(p,div);複製程式碼

結果就是新建立的p元素會取代DOM樹中的div元素。

outerHTML基本不需要考慮相容性問題(firefox7之前版本不支援 其他都不太考慮)

3.insertAdjacentHTML()方法- 插入標記

insertAdjacentHTML()方法接受兩個引數:插入位置和要插入的HTML文字。
第一個引數必須是下列值之一:

'beforebegin',在當前元素之前插入一個緊鄰的同輩元素;
'afterbegin',在當前元素之下插入一個新的子元素或者在第一個子元素之前再插入新的子元素;
'beforeend",在當前元素之下插入一個新的子元素或者在最後一個子元素之後再插入新的子元素;
'afterend',在當前元素之後插入一個緊鄰的同輩元素。
複製程式碼

注意這些值都是小寫形式。

第二個引數是一個HTML字串(與innerHTML和outerHTML的值相同),如果瀏覽器無法解析就會丟擲錯誤。

一下是這個方法的基本用法示例。

//作為前一個同輩元素插入
element.insertAdjacentHTML('beforebegin','<p>HEllo world!</p>");
//作為後一個同輩元素插入
element.insertAdjacentHTML('afterend','<p>HEllo world!</p>");
//作為第一個子元素插入
element.insertAdjacentHTML('afterbegin','<p>HEllo world!</p>");
//作為最後一個子元素插入
element.insertAdjacentHTML('beforeend','<p>HEllo world!</p>");複製程式碼

基本不用考慮相容問題。


4.記憶體與效能問題

這裡介紹的方法替換子節點可能會導致瀏覽器的記憶體佔用問題,尤其在IE.

1.要注意在使用innerHTML、outerHTML屬性和insertAdjacentHTML()方法時,最好先手工刪除要被替換的元素的所有事件處理程式和JavaScript物件屬性。

2.雖然innerHTML屬性比操作DOM效率要高,但也會帶來效能損失,所以設定該屬性的次數要控制在合理的範圍內。



scrollIntoView()滾動頁面方法

scrollIntoiew()可以在所有的HTML元素上呼叫,通過滾動瀏覽器視窗或某個容器元素,呼叫元素就可以出現在視口中。

如果給這個方法傳入true作為引數,或者不傳入任何引數,那麼視窗滾動之後會讓呼叫元素的頂部與視口頂部儘可能平齊。

如果給這個方法傳入false作為引數,呼叫元素會盡可能全部出現在視口中,(可能的話,呼叫元素的底部會與視口底部平齊。)不過頂部不一定平齊。

實際上為某個元素設定焦點也會導致瀏覽器滾動並顯示出獲得焦點的元素。(focus方法)




children屬性

children屬性是HTMLCollection的例項,只包含元素中同樣還是元素的節點。

IE8及更早版本的children屬性中也會包含註釋節點,但IE9之後的版本則只返回元素節點。



contains()方法

通過contains()方法,可以不通過在DOM文件樹中查詢即可獲得這個節點是不是另一個節點的後代。

呼叫contains()方法的應該是祖先節點,接收一個引數,也就是要檢測的後代節點,

如果被檢測的節點是後代節點則返回true;否則返回false;

使用DOM Level 3 compareDocumentPosition()也能夠確定節點間的關係。這個方法用於確定兩個節點間的關係,返回一個表示該關係的位掩碼。

  • 1    -    無關
  • 2    -    居前
  • 4    -    居後
  • 8    -    包含
  • 16  -    被包含



插入文字

1.innerText

通過innerText屬性可以操作元素中包含的所有文字內容,包含子文件樹中的文字。

在通過innerText讀取值時,它會按照由淺入深的順序,將子文件樹中的所有文字拼接起來。

在通過innerText寫入值時,結果會刪除元素的所有子節點,插入包含相應文字值的文字節點。


設定innerText永遠只會生成當前節點的一個子文字節點,而為了確保只生成一個子文字節點,就必須要對文字進行HTML編碼。利用這一點,可以通過innerText屬性過濾掉HTML標籤。方法是將innerText設定為等於innerText,這樣就可以去掉所有HTML標籤。

div.innerText = div.innerText

由於firefox不相容innerText,所以有必要編寫一個函式檢測可以使用哪個屬性。詳情見302。



2.outerText屬性

除了作用範圍擴大到了包含呼叫它的節點之外,outerText和innerText沒啥區別。

在讀取文字值時,outerText和innerText的結果是完全一樣的。

在寫模式下,outerText就完全不同了:outerText不只是替換呼叫它的元素的子節點,而是會替換整個元素(包括子節點),相當於執行了一個replace。

由於呼叫該屬性會導致呼叫它的元素不存在,因此不常用,也不建議儘可能不要用。



滾動

scrollIntoViewIfNeeded(alignCenter):

只在當前元素在視口中不可見的情況下,才滾動瀏覽器視窗或容器元素,最終讓它可見。

如果當前元素在視口中可見,這個方法什麼也不做。

如果將可選的alignCenter引數設定為true,則表示儘量將元素顯示在視口中部(垂直方向)。

Safari和Chrome實現了這個方法


scrollByLines(lineCount):

將元素的內容滾動指定的行高,lineCount值可以是正值,也可以是負值。

Safari和Chrome實現了這個方法


scrollByPages(pageCount):

將元素的內容滾動指定的頁面高度,具體高度由元素的高度決定。

Safari和Chrome實現了這個方法


需要注意的是:scrollIntoView()和scrollIntoViewIfNeeded()的作用物件是元素的容器,而scrollByLines()和scrollByPages()影響的則是元素自身。


DOM擴充套件筆記結束


相關文章