高程3總結#第11章DOM擴充套件
DOM擴充套件
選擇符API
querySelector()方法
-
querySelector()方法接收一個CSS選擇符,返回與該模式匹配的第一個元素,如果沒有找到匹配的元素,返回null
//取得body元素 var body=document.querySelector("body"); //取得ID為"myDiv"的元素 var myDiv=document.querySelector("#myDiv"); //取得類為"selected"的第一個元素 var selected=document.querySelector(".selector"); //取得類為"button"的第一個元素 var img=document.body.querySelector("img.button")
- 如果傳入了不被支援的選擇符,querySelector()會丟擲錯誤
querySelectorAll()方法
- querySelectorAll()方法接收的引數與querySelector()方法一樣,都是一個CSS選擇符,但返回的是所有匹配元素而不是一個元素。這個方法返回的是一個NodeList的例項
-
底層實現類似於一組元素的快照,而非不斷對文件進行搜尋的動態查詢。
//取得某<div>中的所有<em>元素 var em =document.getElementById("myDiv").querySelectorAll("em") //取得類為"selected"的所有元素 var selected=document.querySelectorAll(".selected"); //取得所有<p>元素中的所有<strong>元素 var strongs=document.querySelectorAll("p strong") //要取得返回的NodeList中的每一個元素,可以使用item()方法,也可以使用方括號語法 var i,len,strong; for(i=0,len=strong.length;i<len;i++){ strong=strong[i];//或者strong.item(i) strong.className="important" }
matchesSelector()方法
-
這個方法接收一個引數,即CSS選擇符,如果呼叫元素與該選擇符匹配,返回true,否則返回false
function matchesSelector(element, selector){ if (element.matchesSelector){ return element.matchesSelector(selector); } else if (element.msMatchesSelector){ return element.msMatchesSelector(selector); } else if (element.mozMatchesSelector){ return element.mozMatchesSelector(selector); } else if (element.webkitMatchesSelector){ return element.webkitMatchesSelector(selector); } else { throw new Error("Not supported."); } } if (matchesSelector(document.body, "body.page1")){ //執行操作 }
元素遍歷
-
DOM新增的5個屬性
- childElementCount,返回子元素的個數,不包括文字節點和註釋
- firstElementCount,指向第一個子元素,firstChild的元素版
- lastElementCount,指向最後一個子元素,lastChild的元素版
- previousElementSibling,指向前一個同輩元素,previousSibling的元素版
- nextElementSibling,指向後一個同輩元素,nextSibling的元素版
var i, len, child = element.firstChild; while(child != element.lastChild){ if (child.nodeType == 1){ //檢查是不是元素 processChild(child); } child = child.nextSibling; } //使用新增的元素程式碼會更簡潔 var i, len, child = element.firstElementChild; while(child != element.lastElementChild){ processChild(child); //已知其是元素 child = child.nextElementSibling; }
HTML5
與類相關的補充
- getElementsByClassName()方法接收一個引數,即一個包含一或多個類名的字串,返回帶有制定類的所有元素的NodeList,傳入多個類名時,類名的先後順序不重要。
- getElementsByClassName()始終會返回與類名匹配的所有元素,在元素上呼叫方法就會返回後代元素中匹配的元素。
-
操作類名時可以通過className屬性新增、刪除和替換類名。因為className中是一個字串,所以即使只修改字串的一部分,也必須每次都設定整個字串的值
<div class="bd user disabled">...</div>
//刪除"user"類 //首先,取得類名字串並拆分成陣列 var classNames = div.className.split(/\s+/); //找到要刪的類名 var pos = -1, i, len; for (i=0, len=classNames.length; i < len; i++){ if (classNames[i] == "user"){ pos = i; break; } } //刪除類名 classNames.splice(i,1); //把剩下的類名拼成字串並重新設定 div.className = classNames.join(" ");
-
HTML5為所有元素新增classList屬性,簡化上述操作
- add(value),將給定的字串新增到列表中,如果值已經存在,就不添加了
- contain(value),表示列表中是否存在給定的值,如果存在則返回true,否則返回false
- remove(value),從列表中刪除給定的字串
- toggle(value),如果列表中已經存在給定的值,刪除。如果列表中沒有給定的值,新增。
//刪除"disabled"類 div.classList.remove("disabled"); //新增"current"類 div.classList.add("current"); //切換"user"類 div.classList.toggle("user"); //確定元素中是否包含既定的類名 if (div.classList.contains("bd") && !div.classList.contains("disabled")){ //執行操作 ) //迭代類名 for (var i=0, len=div.classList.length; i < len; i++){ doSomething(div.classList[i]); }
焦點管理
-
document.activeElement屬性會引用DOM中當前獲得了焦點的元素,元素獲得焦點的方式有頁面載入、使用者輸入和在程式碼中呼叫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的變化
-
Document的readyState屬性有兩個可能的值
- loading,正在載入的文件
- complete,已經載入完的文件
-
使用document.readyState的最恰當方式,就是通過它來實現一個指示文件已經載入完成的指示器
if(document.readyState=="complete"){ //執行操作 }
-
document添加了一個名為compatMode的屬性,這個屬性就是為了告訴開發人員瀏覽器採用了哪種渲染模式。標準模式下,document.compatMode的值等於"CSS1Compat",而在混雜模式下,document.compatMode的值等於"BackCompat"
if(document.compatMode=="CSS1Compat"){ alert("Standards mode"); }else { alert("Quirks mode"); }
-
作為對document.body引用文件的<body>元素的補充,HTML5新增了document.head屬性,引用文件的<head>元素,可以結合使用這個屬性和另一種後備方法
var head=document.head||document.getElementByTagName("head")[0];
字符集屬性
自定義資料屬性
-
可以為元素新增非標準的屬性,但要新增字首data-
<div id="myDiv" data-appId="12345" data-myname="Nicholas"></div>
-
可以通過元素的dataset屬性類訪問自定義屬性的值
//本例中使用的方法僅用於演示 var div = document.getElementById("myDiv"); //取得自定義屬性的值 var appId = div.dataset.appId; var myName = div.dataset.myname; //設定值 div.dataset.appId = 23456; div.dataset.myname = "Michael"; //有沒有"myname"值呢? if (div.dataset.myname){ alert("Hello, " + div.dataset.myname); }
插入標記
-
innerHTML
-
在讀模式下,innerHTML屬性返回與呼叫元素的所有子節點對應的HMTL標記。在寫模式下,innerHTML會根據指定的值建立新的DOM樹,然後用這個DOM樹完全替換呼叫元素原先的所有子節點。
<div id="content"> <p>This is a <strong>paragraph</strong> with a list following it.</p> <ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul> </div>
//上面元素innerHTML屬性會返回下面的字串 <p>This is a <strong>paragraph</strong> with a list following it.</p> <ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul>
div.innerHTML="Hello & welcome,<b>\"reader\"!</b>" //操作之後得到下面的HTML程式碼
<div id="content">Hello & welcome, <b>"reader"!</b></div>
- 只要使用innerHTML從外部插入HTML,都應該首先以可靠的方式處理HTML,IE8提供了window.toStationHTML()方法,這個方法接收一個引數,即一個HTML字串,返回一個經過無害處理後的版本,從源HTML中刪除所有指令碼節點和事件處理程式屬性
-
-
outerHTML
-
在讀模式下,outerHTML返回呼叫它的元素及所有子節點的HTML標籤。在寫模式下,outerHTML會根據指定的HTML字串建立新的DOM子樹,然後用這個DOM子樹完全替換呼叫元素
<div id="content"> <p>This is a <strong>paragraph</strong> with a list following it.</p> <ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul> </div>
-
如果呼叫outerHTML會返回和上面相同的程式碼,包括<div>本身
//設定outerHTML屬性 div.outerHTML="<p>This is a paragraph.</p>"
-
-
insertAdjacentHTML
-
接收兩個引數,插入位置和要插入的HTML文辦,第一個引數必須是下列值之一
- beforebegin,在當前元素之前插入一個緊鄰的同輩元素
- afterbegin,在當前元素之前插入一個新的子元素或在第一個子元素之前再插入新的子元素
- beforeend,在當前元素之下插入一個新的子元素或在最後一個子元素之後再插入新的子元素
- afterend,在當前元素之後插入一個緊鄰的同輩元素
-
//作為前一個同輩元素插入
element.insertAdjacentHTML("beforebegin", "<p>Hello world!</p>");
//作為第一個子元素插入
element.insertAdjacentHTML("afterbegin", "<p>Hello world!</p>");
//作為最後一個子元素插入
element.insertAdjacentHTML("beforeend", "<p>Hello world!</p>");
//作為後一個同輩元素插入
element.insertAdjacentHTML("afterend", "<p>Hello world!</p>");
scrollIntoView()方法
-
scrollIntoView()可以在所有HTML元素上呼叫,通過滾動瀏覽器視窗或某個容器元素,呼叫元素就可以出現在視口中,如果給這個方法傳入true作為引數,或者不傳入任何引數,那麼視窗滾動之後會讓呼叫元素的頂部與視口頂部儘可能平齊,如果傳入false作為引數,呼叫元素會盡可能全部出現在視口中
//讓元素可見 document.forms[0]/scrollIntoView();
專有擴充套件
文件模式
-
頁面的文件模式決定了可以使用什麼功能。文件模式決定了可以使用哪個級別的CSS,可以在JavaScript中使用哪些API,以及如何對待文件型別
- IE5,以混雜模式渲染頁面,IE8以及更高的版本功能無法使用
- IE7,以IE7標準模式渲染頁面,IE8以及更高額版本功能無法使用
- IE8,以IE8標準模式渲染頁面,IE8的新功能可以使用,IE9新功能無法使用
- IE9,以IE9標準模式渲染頁面,IE9新功能都可以使用
-
如果想讓文件模式像IE7中一樣,使用以下程式碼
<meta http-qeuiv="X-UA-Compatible" content="IE=EmulateIE7">
-
如果不考慮文件型別宣告,直接使用IE7標準模式
<meta http-equiv="X-UA-Compatible" content="IE=7">
children屬性
-
元素只包含元素子節點時,兩個屬性的值相同
var childCount=element.children.length; var firstChild=element.children[0]
contains()方法
-
呼叫contain()方法的應該是祖先節點,也就是搜尋開始的節點,這個方法接收一個引數,即要檢測的後代節點。如果被檢測的節點是後代節點,該方法返回true,否則返回false
alert(document.documentElement.contain(document.body))//true
-
使用瀏覽器及能力檢測,寫出通用的contain函式
function contains(refNode, otherNode){ if (typeof refNode.contains == "function" && (!client.engine.webkit || client.engine.webkit >= 522)){ return refNode.contains(otherNode); } else if (typeof refNode.compareDocumentPosition == "function"){ return !!(refNode.compareDocumentPosition(otherNode) & 16); } else { var node = otherNode.parentNode; do { if (node === refNode){ return true; } else { node = node.parentNode; } } while (node !== null); return false; } }
插入文字
-
innerText
-
通過這個屬性可以操作元素中包含的所有文字內容,包括子文件樹中的文字,在通過innerText讀取值時,它會按照由淺入深的順序,將子文件樹中的所有文字拼接起來,在通過innerText寫入值時,結果會刪除元素的所有子節點,插入包含相應文字值的文字節點
<div id="content"> <p>This is a <strong>paragraph</strong> with a list following it.</p> <ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul> </div>
//對於上面的<div>元素而言,其innerText屬性會返回下列字串 This is a paragraph with a list following it. Item 1 Item 2 Item 3
-
設定這個屬性
div.innerText="Hello world"; //執行完之後結果是下方程式碼
<div id="content">Hello world!</div>
- 編寫程式碼檢測屬性
function getInnerText(element){ return (typeof element.textContent == "string") ? element.textContent : element.innerText; } function setInnerText(element, text){ if (typeof element.textContent == "string"){ element.textContent = text; } else { element.innerText = text; } }
-
-
outerText
- outerText不只是替換它元素的自己誒單,而是會替換整個元素,包括子節點
滾動
-
對HTMLElement型別拓展的幾個方法
- scrollIntoViewIfNeeded(alignCenter) :只在當前元素在視口中不可見的情況下,才滾動瀏覽器視窗或容器元素,最終讓它可見。如果當前元素在視口中可見,這個方法什麼也不做。如果將可選的 alignCenter 引數設定為 true ,則表示儘量將元素顯示在視口中部(垂直方向)。Safari 和 Chrome 實現了這個方法。
- scrollByLines(lineCount) :將元素的內容滾動指定的行高, lineCount 值可以是正值,也可以是負值。Safari 和 Chrome 實現了這個方法。
- scrollByPages(pageCount) :將元素的內容滾動指定的頁面高度,具體高度由元素的高度決定。Safari 和 Chrome 實現了這個方法。
//將頁面主體滾動 5 行 document.body.scrollByLines(5); //在當前元素不可見的時候,讓它進入瀏覽器的視口 document.images[0].scrollIntoViewIfNeeded(); //將頁面主體往回滾動 1 頁 document.body.scrollByPages(-1);