JavaScript document節(jié)點

2018-07-24 11:52 更新

目錄

概述

document節(jié)點是文檔的根節(jié)點,每張網(wǎng)頁都有自己的document節(jié)點。window.document屬性就指向這個節(jié)點。只要瀏覽器開始載入HTML文檔,這個節(jié)點對象就存在了,可以直接調(diào)用。

document節(jié)點有不同的辦法可以獲取。

  • 對于正常的網(wǎng)頁,直接使用documentwindow.document。
  • 對于iframe載入的網(wǎng)頁,使用iframe節(jié)點的contentDocument屬性。
  • 對Ajax操作返回的文檔,使用XMLHttpRequest對象的responseXML屬性。
  • 對于包含某個節(jié)點的文檔,使用該節(jié)點的ownerDocument屬性。

上面這四種document節(jié)點,都部署了Document接口,因此有共同的屬性和方法。當(dāng)然,各自也有一些自己獨特的屬性和方法,比如HTML和XML文檔的document節(jié)點就不一樣。

內(nèi)部節(jié)點屬性

document節(jié)點有很多屬性,其中相當(dāng)一部分屬于快捷方式,指向文檔內(nèi)部的某個節(jié)點。

document.doctype,document.documentElement,document.defaultView

對于HTML文檔來說,document對象一般有兩個子節(jié)點。第一個子節(jié)點是document.doctype,它是一個對象,包含了當(dāng)前文檔類型(Document Type Declaration,簡寫DTD)信息。對于HTML5文檔,該節(jié)點就代表<!DOCTYPE html>。如果網(wǎng)頁沒有聲明DTD,該屬性返回null。

var doctype = document.doctype;
doctype // "<!DOCTYPE html>"
doctype.name // "html"

document.firstChild通常就返回這個節(jié)點。

document.documentElement屬性返回當(dāng)前文檔的根節(jié)點(root)。它通常是document節(jié)點的第二個子節(jié)點,緊跟在document.doctype節(jié)點后面。對于HTML網(wǎng)頁,該屬性返回<html>節(jié)點。

document.defaultView屬性,在瀏覽器中返回document對象所在的window對象,否則返回null。

document.defaultView === window // true

document.body,document.head

document.head屬性返回當(dāng)前文檔的<head>節(jié)點,document.body屬性返回當(dāng)前文檔的<body>。

document.head === document.querySelector('head') // true
document.body === document.querySelector('body') // true

這兩個屬性總是存在的,如果網(wǎng)頁源碼里面省略了<head><body>,瀏覽器會自動創(chuàng)造。另外,這兩個屬性是可寫的,如果對其寫入一個新的節(jié)點,會導(dǎo)致原有的所有子節(jié)點被移除。

document.activeElement

document.activeElement屬性返回當(dāng)前文檔中獲得焦點的那個元素。用戶通常可以使用Tab鍵移動焦點,使用空格鍵激活焦點。比如,如果焦點在一個鏈接上,此時按一下空格鍵,就會跳轉(zhuǎn)到該鏈接。

節(jié)點集合屬性

以下屬性返回文檔內(nèi)部特定元素的集合,都是類似數(shù)組的對象。這些集合都是動態(tài)的,原節(jié)點有任何變化,立刻會反映在集合中。

document.links,document.forms,document.images,document.embeds

document.links屬性返回當(dāng)前文檔所有設(shè)定了href屬性的aarea元素。

document.forms屬性返回頁面中所有表單元素form。

var selectForm = document.forms[0];

上面代碼獲取文檔第一個表單。

document.images屬性返回頁面所有圖片元素(即img標(biāo)簽)。

var imglist = document.images;

for(var i = 0; i < imglist.length; i++) {
  if (imglist[i].src === 'banner.gif') {
    // ...
  }
}

上面代碼在所有img標(biāo)簽中,尋找特定圖片。

document.embeds屬性返回網(wǎng)頁中所有嵌入對象,即embed標(biāo)簽。

以上四個屬性返回的都是HTMLCollection對象實例。

document.links instanceof HTMLCollection // true
document.images instanceof HTMLCollection // true
document.forms instanceof HTMLCollection // true
document.embeds instanceof HTMLCollection // true

由于HTMLCollection實例可以用HTML元素的idname屬性引用,因此如果一個元素有idname屬性,就可以在上面這四個屬性上引用。

// HTML代碼為
// <form name="myForm" >

document.myForm === document.forms.myForm // true

document.scripts,document.styleSheets

document.scripts屬性返回當(dāng)前文檔的所有腳本(即script標(biāo)簽)。

var scripts = document.scripts;
if (scripts.length !== 0 ) {
  console.log('當(dāng)前網(wǎng)頁有腳本');
}

document.scripts返回的也是HTMLCollection實例。

document.scripts instanceof HTMLCollection // true

因此,如果一個script標(biāo)簽有idname屬性,就可以在document.scripts上引用。

// HTML代碼為
// <script id="myScript" >

document.scripts.myScript
// <script id="myScript"></script>

document.styleSheets屬性返回一個類似數(shù)組的對象,代表當(dāng)前網(wǎng)頁的所有樣式表。每個樣式表對象都有cssRules屬性,返回該樣式表的所有CSS規(guī)則,這樣這可以操作具體的CSS規(guī)則了。

var allSheets = [].slice.call(document.styleSheets);

上面代碼中,使用slice方法將document.styleSheets轉(zhuǎn)為數(shù)組,以便于進一步處理。

文檔信息屬性

以下屬性返回文檔信息。

document.documentURI,document.URL

document.documentURI屬性和document.URL屬性都返回一個字符串,表示當(dāng)前文檔的網(wǎng)址。不同之處是documentURI屬性是所有文檔都具備的,URL屬性則是HTML文檔獨有的。

document.documentURI === document.URL
// true

另外,如果文檔的錨點(#anchor)變化,這兩個屬性都不會跟著變化,它們的值是靜態(tài)的。但是,document.location會跟著變化,document.location總是返回最新的URL,會跟蹤錨點的變化。

document.domain

document.domain屬性返回當(dāng)前文檔的域名。比如,某張網(wǎng)頁的網(wǎng)址是 http://www.example.com/hello.html ,domain屬性就等于www.example.com。如果無法獲取域名,該屬性返回null。

var badDomain = 'www.example.xxx';
if (document.domain === badDomain)
  window.close();

上面代碼判斷,如果當(dāng)前域名等于指定域名,則關(guān)閉窗口。

二級域名的情況下,domain屬性可以設(shè)置為對應(yīng)的一級域名。比如,當(dāng)前域名是sub.example.com,則domain屬性可以設(shè)置為example.com。除此之外的寫入,都是不可以的。

document.lastModified

document.lastModified屬性返回當(dāng)前文檔最后修改的時間戳,格式為字符串。

document.lastModified
// Tuesday, July 10, 2001 10:19:42

注意,lastModified屬性的值是字符串,所以不能用來直接比較,兩個文檔誰的日期更新,需要用Date.parse方法轉(zhuǎn)成時間戳格式,才能進行比較。

if (Date.parse(doc1.lastModified) > Date.parse(doc2.lastModified)) {
  // ...
}

document.location

document.location屬性返回location對象,提供了當(dāng)前文檔的URL信息。

// 當(dāng)前網(wǎng)址為 http://user:passwd@www.example.com:4097/path/a.html?x=111#part1
document.location.href // "http://user:passwd@www.example.com:4097/path/a.html?x=111#part1"
document.location.protocol // "http:"
document.location.host // "www.example.com:4097"
document.location.hostname // "www.example.com"
document.location.port // "4097"
document.location.pathname // "/path/a.html"
document.location.search // "?x=111"
document.location.hash // "#part1"
document.location.user // "user"
document.location.password // "passed"

location對象有以下方法。

  • location.assign()
  • location.reload()
  • location.toString()
// 跳轉(zhuǎn)到另一個網(wǎng)址
document.location.assign('http://www.google.com')
// 優(yōu)先從服務(wù)器重新加載
document.location.reload(true)
// 優(yōu)先從本地緩存重新加載(默認(rèn)值)
document.location.reload(false)
// 跳轉(zhuǎn)到新網(wǎng)址,并將取代掉history對象中的當(dāng)前記錄
document.location.replace('http://www.google.com');
// 將location對象轉(zhuǎn)為字符串,等價于document.location.href
document.location.toString()

如果將新的網(wǎng)址賦值給location對象,網(wǎng)頁就會自動跳轉(zhuǎn)到新網(wǎng)址。

document.location = 'http://www.example.com';
// 等同于
document.location.href = 'http://www.example.com';

也可以指定相對URL。

document.location = 'page2.html';

如果指定的是錨點,瀏覽器會自動滾動到錨點處。

document.location = '#top';

注意,采用上面的方法重置URL,跟用戶點擊鏈接跳轉(zhuǎn)的效果是一樣的。上一個網(wǎng)頁依然將保存在瀏覽器歷史之中,點擊“后退”按鈕就可以回到前一個網(wǎng)頁。

如果不希望用戶看到前一個網(wǎng)頁,可以使用location.replace方法,瀏覽器history對象就會用新的網(wǎng)址,取代當(dāng)前網(wǎng)址,這樣的話,“后退”按鈕就不會回到當(dāng)前網(wǎng)頁了。它的一個應(yīng)用就是,當(dāng)腳本發(fā)現(xiàn)當(dāng)前是移動設(shè)備時,就立刻跳轉(zhuǎn)到移動版網(wǎng)頁。

document.location屬性與window.location屬性等價。

document.location === window.location // true

歷史上,IE曾經(jīng)不允許對document.location賦值,為了保險起見,建議優(yōu)先使用window.location。如果只是單純地獲取當(dāng)前網(wǎng)址,建議使用document.URL,語義性更好。

document.referrer,document.title,document.characterSet

document.referrer屬性返回一個字符串,表示當(dāng)前文檔的訪問來源,如果是無法獲取來源或是用戶直接鍵入網(wǎng)址,而不是從其他網(wǎng)頁點擊,則返回一個空字符串。

document.referrer的值,總是與HTTP頭信息的Referer保持一致,但是它的拼寫有兩個r。

document.title屬性返回當(dāng)前文檔的標(biāo)題,該屬性是可寫的。

document.title = '新標(biāo)題';

document.characterSet屬性返回渲染當(dāng)前文檔的字符集,比如UTF-8、ISO-8859-1。

document.readyState

document.readyState屬性返回當(dāng)前文檔的狀態(tài),共有三種可能的值。

  • loading:加載HTML代碼階段(尚未完成解析)
  • interactive:加載外部資源階段時
  • complete:加載完成時

這個屬性變化的過程如下。

  1. 瀏覽器開始解析HTML文檔,document.readyState屬性等于loading。
  2. 瀏覽器遇到HTML文檔中的<script>元素,并且沒有asyncdefer屬性,就暫停解析,開始執(zhí)行腳本,這時document.readyState屬性還是等于loading。
  3. HTML文檔解析完成,document.readyState屬性變成interactive。
  4. 瀏覽器等待圖片、樣式表、字體文件等外部資源加載完成,一旦全部加載完成,document. readyState屬性變成complete。

下面的代碼用來檢查網(wǎng)頁是否加載成功。

// 基本檢查
if (document.readyState === 'complete') {
  // ...
}

// 輪詢檢查
var interval = setInterval(function() {
  if (document.readyState === 'complete') {
    clearInterval(interval);
    // ...
  }
}, 100);

document.designMode

document.designMode屬性控制當(dāng)前文檔是否可編輯,通常用在制作所見即所得編輯器。打開iframe元素包含的文檔的designMode屬性,就能將其變?yōu)橐粋€所見即所得的編輯器。

<iframe id="editor" src="about:blank"></iframe>
<script>
!(function () {
  var editor = document.getElementById('editor');
  editor.contentDocument.designMode = 'on';
})();
</script>

document.implementation

document.implementation屬性返回一個對象,用來甄別當(dāng)前環(huán)境部署了哪些DOM相關(guān)接口。implementation屬性的hasFeature方法,可以判斷當(dāng)前環(huán)境是否部署了特定版本的特定接口。

document.implementation.hasFeature('HTML', '2.0')
// true

document.implementation.hasFeature('MutationEvents','2.0')
// true

上面代碼表示,當(dāng)前環(huán)境部署了DOM HTML 2.0版和MutationEvents的2.0版。

document.compatMode

compatMode屬性返回瀏覽器處理文檔的模式,可能的值為BackCompat(向后兼容模式)和CSS1Compat(嚴(yán)格模式)。

一般來說,如果網(wǎng)頁代碼的第一行設(shè)置了明確的DOCTYPE(比如<!doctype html>),document.compatMode的值都為CSS1Compat。

document.cookie

document.cookie屬性用來操作瀏覽器Cookie,詳見《瀏覽器環(huán)境》一章的《Cookie》部分。

讀寫相關(guān)的方法

document.open(),document.close()

document.open方法用于新建一個文檔,供write方法寫入內(nèi)容。它實際上等于清除當(dāng)前文檔,重新寫入內(nèi)容。不要將此方法與window.open()混淆,后者用來打開一個新窗口,與當(dāng)前文檔無關(guān)。

document.close方法用于關(guān)閉open方法所新建的文檔。一旦關(guān)閉,write方法就無法寫入內(nèi)容了。如果再調(diào)用write方法,就等同于又調(diào)用open方法,新建一個文檔,再寫入內(nèi)容。

document.write(),document.writeln()

document.write方法用于向當(dāng)前文檔寫入內(nèi)容。只要當(dāng)前文檔還沒有用close方法關(guān)閉,它所寫入的內(nèi)容就會追加在已有內(nèi)容的后面。

// 頁面顯示“helloworld”
document.open();
document.write('hello');
document.write('world');
document.close();

注意,document.write會當(dāng)作HTML代碼解析,不會轉(zhuǎn)義。

document.write('<p>hello world</p>');

如果頁面已經(jīng)解析完成(DOMContentLoaded事件發(fā)生之后),再調(diào)用write方法,它會先調(diào)用open方法,擦除當(dāng)前文檔所有內(nèi)容,然后再寫入。

document.addEventListener('DOMContentLoaded', function (event) {
  document.write('<p>Hello World!</p>');
});

// 等同于

document.addEventListener('DOMContentLoaded', function (event) {
  document.open();
  document.write('<p>Hello World!</p>');
  document.close();
});

如果在頁面渲染過程中調(diào)用write方法,并不會調(diào)用open方法。(可以理解成,open方法已調(diào)用,但close方法還未調(diào)用。)

<html>
<body>
hello
<script type="text/javascript">
  document.write("world")
</script>
</body>
</html>

在瀏覽器打開上面網(wǎng)頁,將會顯示hello world

document.write是JavaScript語言標(biāo)準(zhǔn)化之前就存在的方法,現(xiàn)在完全有更符合標(biāo)準(zhǔn)的方法向文檔寫入內(nèi)容(比如對innerHTML屬性賦值)。所以,除了某些特殊情況,應(yīng)該盡量避免使用document.write這個方法。

document.writeln方法與write方法完全一致,除了會在輸出內(nèi)容的尾部添加換行符。

document.write(1);
document.write(2);
// 12

document.writeln(1);
document.writeln(2);
// 1
// 2
//

注意,writeln方法添加的是ASCII碼的換行符,渲染成HTML網(wǎng)頁時不起作用,即在網(wǎng)頁上顯示不出換行。

查找節(jié)點的方法

以下方法用來查找某個節(jié)點。

document.querySelector(),document.querySelectorAll()

document.querySelector方法接受一個CSS選擇器作為參數(shù),返回匹配該選擇器的元素節(jié)點。如果有多個節(jié)點滿足匹配條件,則返回第一個匹配的節(jié)點。如果沒有發(fā)現(xiàn)匹配的節(jié)點,則返回null

var el1 = document.querySelector('.myclass');
var el2 = document.querySelector('#myParent > [ng-click]');

document.querySelectorAll方法與querySelector用法類似,區(qū)別是返回一個NodeList對象,包含所有匹配給定選擇器的節(jié)點。

elementList = document.querySelectorAll('.myclass');

這兩個方法的參數(shù),可以是逗號分隔的多個CSS選擇器,返回匹配其中一個選擇器的元素節(jié)點。

var matches = document.querySelectorAll('div.note, div.alert');

上面代碼返回class屬性是notealertdiv元素。

這兩個方法都支持復(fù)雜的CSS選擇器。

// 選中data-foo-bar屬性等于someval的元素
document.querySelectorAll('[data-foo-bar="someval"]');

// 選中myForm表單中所有不通過驗證的元素
document.querySelectorAll('#myForm :invalid');

// 選中div元素,那些class含ignore的除外
document.querySelectorAll('DIV:not(.ignore)');

// 同時選中div,a,script三類元素
document.querySelectorAll('DIV, A, SCRIPT');

但是,它們不支持CSS偽元素的選擇器(比如:first-line:first-letter)和偽類的選擇器(比如:link:visited),即無法選中偽元素和偽類。

如果querySelectorAll方法的參數(shù)是字符串*,則會返回文檔中的所有HTML元素節(jié)點。另外,querySelectorAll的返回結(jié)果不是動態(tài)集合,不會實時反映元素節(jié)點的變化。

最后,這兩個方法除了定義在document對象上,還定義在元素節(jié)點上,即在元素節(jié)點上也可以調(diào)用。

document.getElementsByTagName()

document.getElementsByTagName方法返回所有指定HTML標(biāo)簽的元素,返回值是一個類似數(shù)組的HTMLCollection對象,可以實時反映HTML文檔的變化。如果沒有任何匹配的元素,就返回一個空集。

var paras = document.getElementsByTagName('p');

paras instanceof HTMLCollection // true

上面代碼返回當(dāng)前文檔的所有p元素節(jié)點。

HTML標(biāo)簽名是大小寫不敏感的,因此getElementsByTagName方法也是大小寫不敏感的。另外,返回結(jié)果中,各個成員的順序就是它們在文檔中出現(xiàn)的順序。

如果傳入*,就可以返回文檔中所有HTML元素。

var allElements = document.getElementsByTagName('*');

注意,HTML元素本身也定義了getElementsByTagName方法,返回該元素的后代元素中符合指定標(biāo)簽的元素。也就是說,這個方法不僅可以在document對象上調(diào)用,也可以在任何元素節(jié)點上調(diào)用。

var firstPara = document.getElementsByTagName('p')[0];
var spans = firstPara.getElementsByTagName('span');

上面代碼選中第一個p元素內(nèi)部的所有span元素。

document.getElementsByClassName()

document.getElementsByClassName方法返回一個類似數(shù)組的對象(HTMLCollection實例對象),包括了所有class名字符合指定條件的元素,元素的變化實時反映在返回結(jié)果中。

var elements = document.getElementsByClassName(names);

由于class是保留字,所以JavaScript一律使用className表示CSS的class。

如果參數(shù)是一個空格分隔的字符串,元素的class必須符合所有字符串之中所有的class才會返回。

var elements = document.getElementsByClassName('foo bar');

上面代碼返回同時具有foobar兩個class的元素,foobar的順序不重要。

注意,正常模式下,CSS的class是大小寫敏感的。(quirks mode下,大小寫不敏感。)

getElementsByTagName方法一樣,getElementsByClassName方法不僅可以在document對象上調(diào)用,也可以在任何元素節(jié)點上調(diào)用。

// 非document對象上調(diào)用
var elements = rootElement.getElementsByClassName(names);

document.getElementsByName()

document.getElementsByName方法用于選擇擁有name屬性的HTML元素(比如<form>、<radio>、<img>、<frame>、<embed><object>等),返回一個類似數(shù)組的的對象(NodeList對象的實例),因為name屬性相同的元素可能不止一個。

// 表單為 <form name="x"></form>
var forms = document.getElementsByName('x');
forms[0].tagName // "FORM"

getElementById()

getElementById方法返回匹配指定id屬性的元素節(jié)點。如果沒有發(fā)現(xiàn)匹配的節(jié)點,則返回null。

var elem = document.getElementById('para1');

注意,該方法的參數(shù)是大小寫敏感的。比如,如果某個節(jié)點的id屬性是main,那么document.getElementById('Main')將返回null,而不是那個節(jié)點。

document.getElementById方法與document.querySelector方法都能獲取元素節(jié)點,不同之處是document.querySelector方法的參數(shù)使用CSS選擇器語法,document.getElementById方法的參數(shù)是HTML標(biāo)簽元素的id屬性。

document.getElementById('myElement')
document.querySelector('#myElement')

上面代碼中,兩個方法都能選中idmyElement的元素,但是getElementById()querySelector()效率高得多。

另外,這個方法只能在document對象上使用,不能在其他元素節(jié)點上使用。

document.elementFromPoint()

document.elementFromPoint方法返回位于頁面指定位置最上層的Element子節(jié)點。

var element = document.elementFromPoint(50, 50);

上面代碼選中在(50, 50)這個坐標(biāo)位置的最上層的那個HTML元素。

elementFromPoint方法的兩個參數(shù),依次是相對于當(dāng)前視口左上角的橫坐標(biāo)和縱坐標(biāo),單位是像素。如果位于該位置的HTML元素不可返回(比如文本框的滾動條),則返回它的父元素(比如文本框)。如果坐標(biāo)值無意義(比如負(fù)值或超過視口大小),則返回null

生成節(jié)點的方法

以下方法用于生成元素節(jié)點。

document.createElement()

document.createElement方法用來生成網(wǎng)頁元素節(jié)點。

var newDiv = document.createElement('div');

createElement方法的參數(shù)為元素的標(biāo)簽名,即元素節(jié)點的tagName屬性,對于 HTML 網(wǎng)頁大小寫不敏感,即參數(shù)為divDIV返回的是同一種節(jié)點。如果參數(shù)里面包含尖括號(即<>)會報錯。

document.createElement('<div>')
// DOMException: The tag name provided ('<div>') is not a valid name

document.createTextNode()

document.createTextNode方法用來生成文本節(jié)點,參數(shù)為所要生成的文本節(jié)點的內(nèi)容。

var newDiv = document.createElement('div');
var newContent = document.createTextNode('Hello');
newDiv.appendChild(newContent);

上面代碼新建一個div節(jié)點和一個文本節(jié)點,然后將文本節(jié)點插入div節(jié)點。

這個方法可以確保返回的節(jié)點,被瀏覽器當(dāng)作文本渲染,而不是當(dāng)作HTML代碼渲染。因此,可以用來展示用戶的輸入,避免XSS攻擊。

var div = document.createElement('div');
div.appendChild(document.createTextNode('<span>Foo & bar</span>'));
console.log(div.innerHTML)
// &lt;span&gt;Foo &amp; bar&lt;/span&gt;

上面代碼中,createTextNode方法對大于號和小于號進行轉(zhuǎn)義,從而保證即使用戶輸入的內(nèi)容包含惡意代碼,也能正確顯示。

需要注意的是,該方法不對單引號和雙引號轉(zhuǎn)義,所以不能用來對HTML屬性賦值。

function escapeHtml(str) {
  var div = document.createElement('div');
  div.appendChild(document.createTextNode(str));
  return div.innerHTML;
};

var userWebsite = '" onmouseover="alert(\'derp\')" "';
var profileLink = '<a href="' + escapeHtml(userWebsite) + '">Bob</a>';
var div = document.getElemenetById('target');
div.innerHtml = profileLink;
// <a href="" onmouseover="alert('derp')" "">Bob</a>

上面代碼中,由于createTextNode方法不轉(zhuǎn)義雙引號,導(dǎo)致onmouseover方法被注入了代碼。

document.createAttribute()

document.createAttribute方法生成一個新的屬性對象節(jié)點,并返回它。

attribute = document.createAttribute(name);

createAttribute方法的參數(shù)name,是屬性的名稱。

var node = document.getElementById("div1");
var a = document.createAttribute("my_attrib");
a.value = "newVal";
node.setAttributeNode(a);

// 等同于

var node = document.getElementById("div1");
node.setAttribute("my_attrib", "newVal");

document.createDocumentFragment()

createDocumentFragment方法生成一個DocumentFragment對象。

var docFragment = document.createDocumentFragment();

DocumentFragment對象是一個存在于內(nèi)存的DOM片段,但是不屬于當(dāng)前文檔,常常用來生成較復(fù)雜的DOM結(jié)構(gòu),然后插入當(dāng)前文檔。這樣做的好處在于,因為DocumentFragment不屬于當(dāng)前文檔,對它的任何改動,都不會引發(fā)網(wǎng)頁的重新渲染,比直接修改當(dāng)前文檔的DOM有更好的性能表現(xiàn)。

var docfrag = document.createDocumentFragment();

[1, 2, 3, 4].forEach(function(e) {
  var li = document.createElement("li");
  li.textContent = e;
  docfrag.appendChild(li);
});

document.body.appendChild(docfrag);

事件相關(guān)的方法

document.createEvent()

document.createEvent方法生成一個事件對象,該對象可以被element.dispatchEvent方法使用,觸發(fā)指定事件。

var event = document.createEvent(type);

createEvent方法的參數(shù)是事件類型,比如UIEvents、MouseEvents、MutationEvents、HTMLEvents。

var event = document.createEvent('Event');
event.initEvent('build', true, true);
document.addEventListener('build', function (e) {
  // ...
}, false);
document.dispatchEvent(event);

document.addEventListener(),document.removeEventListener(),document.dispatchEvent()

以下三個方法與document節(jié)點的事件相關(guān)。這些方法都繼承自EventTarget接口,詳細(xì)介紹參見《Event對象》章節(jié)的《EventTarget》部分。

// 添加事件監(jiān)聽函數(shù)
document.addEventListener('click', listener, false);

// 移除事件監(jiān)聽函數(shù)
document.removeEventListener('click', listener, false);

// 觸發(fā)事件
var event = new Event('click');
document.dispatchEvent(event);

其他方法

document.hasFocus()

document.hasFocus方法返回一個布爾值,表示當(dāng)前文檔之中是否有元素被激活或獲得焦點。

var focused = document.hasFocus();

注意,有焦點的文檔必定被激活(active),反之不成立,激活的文檔未必有焦點。比如如果用戶點擊按鈕,從當(dāng)前窗口跳出一個新窗口,該新窗口就是激活的,但是不擁有焦點。

document.createNodeIterator(),document.createTreeWalker()

以下方法用于遍歷元素節(jié)點。

(1)document.createNodeIterator()

document.createNodeIterator方法返回一個DOM的子節(jié)點遍歷器。

var nodeIterator = document.createNodeIterator(
  document.body,
  NodeFilter.SHOW_ELEMENT
);

上面代碼返回body元素的遍歷器。createNodeIterator方法的第一個參數(shù)為遍歷器的根節(jié)點,第二個參數(shù)為所要遍歷的節(jié)點類型,這里指定為元素節(jié)點。其他類型還有所有節(jié)點(NodeFilter.SHOW_ALL)、文本節(jié)點(NodeFilter.SHOW_TEXT)、評論節(jié)點(NodeFilter.SHOW_COMMENT)等。

所謂“遍歷器”,在這里指可以用nextNode方法和previousNode方法依次遍歷根節(jié)點的所有子節(jié)點。

var nodeIterator = document.createNodeIterator(document.body);
var pars = [];
var currentNode;

while (currentNode = nodeIterator.nextNode()) {
  pars.push(currentNode);
}

上面代碼使用遍歷器的nextNode方法,將根節(jié)點的所有子節(jié)點,按照從頭部到尾部的順序,讀入一個數(shù)組。nextNode方法先返回遍歷器的內(nèi)部指針?biāo)诘墓?jié)點,然后會將指針移向下一個節(jié)點。所有成員遍歷完成后,返回null。previousNode方法則是先將指針移向上一個節(jié)點,然后返回該節(jié)點。

var nodeIterator = document.createNodeIterator(
  document.body,
  NodeFilter.SHOW_ELEMENT
);

var currentNode = nodeIterator.nextNode();
var previousNode = nodeIterator.previousNode();

currentNode === previousNode // true

上面代碼中,currentNode和previousNode都指向同一個的節(jié)點。

有一個需要注意的地方,遍歷器返回的第一個節(jié)點,總是根節(jié)點。

(2)document.createTreeWalker()

document.createTreeWalker方法返回一個DOM的子樹遍歷器。它與createNodeIterator方法的區(qū)別在于,后者只遍歷子節(jié)點,而它遍歷整個子樹。

document.createTreeWalker方法的第一個參數(shù),是所要遍歷的根節(jié)點,第二個參數(shù)指定所要遍歷的節(jié)點類型。

var treeWalker = document.createTreeWalker(
  document.body,
  NodeFilter.SHOW_ELEMENT
);

var nodeList = [];

while(treeWalker.nextNode()) nodeList.push(treeWalker.currentNode);

上面代碼遍歷body節(jié)點下屬的所有元素節(jié)點,將它們插入nodeList數(shù)組。

document.adoptNode()

document.adoptNode方法將某個節(jié)點,從其原來所在的文檔移除,插入當(dāng)前文檔,并返回插入后的新節(jié)點。

node = document.adoptNode(externalNode);

document.importNode()

document.importNode方法從外部文檔拷貝指定節(jié)點,插入當(dāng)前文檔。

var node = document.importNode(externalNode, deep);

document.importNode方法用于創(chuàng)造一個外部節(jié)點的拷貝,然后插入當(dāng)前文檔。它的第一個參數(shù)是外部節(jié)點,第二個參數(shù)是一個布爾值,表示對外部節(jié)點是深拷貝還是淺拷貝,默認(rèn)是淺拷貝(false)。雖然第二個參數(shù)是可選的,但是建議總是保留這個參數(shù),并設(shè)為true

注意,importNode方法只是拷貝外部節(jié)點,這時該節(jié)點的父節(jié)點是null。下一步還必須將這個節(jié)點插入當(dāng)前文檔的DOM樹。

var iframe = document.getElementsByTagName('iframe')[0];
var oldNode = iframe.contentWindow.document.getElementById('myNode');
var newNode = document.importNode(oldNode, true);
document.getElementById("container").appendChild(newNode);

上面代碼從iframe窗口,拷貝一個指定節(jié)點myNode,插入當(dāng)前文檔。

document.getSelection()

這個方法指向window.getSelection(),參見window對象一節(jié)的介紹。

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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號