jsdom 中文文檔(純翻譯)

jsdom是一個純粹由 javascript 實現的一系列 web標準,特別是 WHATWG 組織制定的DOMHTML 標準,用於在 nodejs 中使用。大致上來講,該項目的目標是模擬足夠的Web瀏覽器子集,以便用於測試和挖掘真實世界的Web應用程序。javascript

最新版本的 jsdom 運行環境須要 node.js v6或者更高的版本。(jsdom v10如下版本在 nodejs v4如下仍然可用,可是咱們已經不支持維護了)html

v10版本的 jsdom 擁有全新的 API(以下所述).舊的 API 如今仍然支持;詳細的參照文檔java

基本用法

const jsdom = require("jsdom");
const { JSDOM } = jsdom;

爲了使用 jsdom,主要用到jsdom主模塊的一個命名導出的 jsdom 構造函數。往構造器傳遞一個字符串,將會獲得一個 jsdom 構造實例對象,這個對象有不少實用的屬性,特別是 window 對象:node

const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`);
console.log(dom.window.document.querySelector("p").textContent); // "Hello world"

(請注意,jsdom會像瀏覽器同樣解析您傳遞的HTML,包括隱含的<html><head><body>標記)git

生成的對象是JSDOM類的一個實例,其中包括 window 對象在內的許多有用的屬性和方法。通常來講,它能夠用來從「外部」對jsdom進行操做,而這些操做對於普通DOM API來講是不可能的。對於不須要任何功能的簡單場景,咱們推薦使用相似的編碼模式github

const { window } = new JSDOM(`...`);
// or even
const { document } = (new JSDOM(`...`)).window;

下面是關於JSDOM類所能作的一切的完整文檔,在「JSDOM對象API」部分。web

定製 jsdom

JSDOM構造函數接受第二個參數,能夠用如下方式定製您的jsdom。npm

簡單選項

const dom = new JSDOM(``, {
  url: "https://example.org/",
  referrer: "https://example.com/",
  contentType: "text/html",
  userAgent: "Mellblomenator/9000",
  includeNodeLocations: true
});
  • url 設置的值能夠經過window.locationdocument.URLdocument.documentURI來返回,並會影響文檔中相關URL的解析以及獲取子資源時使用的同源限制和referrer。默認值爲"about:blank"
  • referrer 僅僅影響document.referrer的值。默認沒有引用(即爲空字符串)。
  • contentType 影響document.contentType的值,是按照HTML解析文檔仍是 XML來解析。它的值若是不是text/htmlXML mime type 值的話將會拋出異常。默認值爲"text/html"
  • userAgent 影響navigator.userAgent的值以及請求子資源時發送的User-Agent頭。默認值爲Mozilla / 5.0($ {process.platform})AppleWebKit / 537.36(KHTML,如Gecko)jsdom / $ {jsdomVersion}
  • includeNodeLocations 保留由HTML解析器生成的位置信息,容許您使用nodeLocation()方法(以下所述)檢索它。

它還能確保在<script>元素內運行的代碼的異常堆棧跟蹤中報告的行號是正確的。
默認值爲false以提供最佳性能,而且不能與XML內容類型一塊兒使用,由於咱們的XML解析器不支持位置信息。canvas

請注意urlreferrer在使用以前已經被規範化了,例如
若是你傳入"https:example.com",jsdom會自動規範化解釋爲"https://example.com/"
若是你傳遞了一個不可解析的URL,該調用將拋出錯誤。
(URL根據URL標準進行分析和序列化。)api

執行腳本

jsdom最強大的功能是它能夠在jsdom中執行腳本。這些腳本能夠修改頁面的內容並訪問jsdom實現的全部Web平臺API。

可是,這在處理不可信內容時也很是危險。
jsdom沙箱並非萬無一失的,在DOM的<script>內部運行的代碼若是足夠深刻,就能夠訪問Node.js環境,從而訪問您的計算機。
所以,默認狀況下,執行嵌入在HTML中的腳本的功能是禁用的:

const dom = new JSDOM(`<body>
  <script>document.body.appendChild(document.createElement("hr"));</script>
</body>`);

// 腳本默認將不能執行:
dom.window.document.body.children.length === 1;

要在頁面內啓用腳本,可使用runScripts:"dangerously"選項:

const dom = new JSDOM(`<body>
  <script>document.body.appendChild(document.createElement("hr"));</script>
</body>`, { runScripts: "dangerously" });

// 腳本將執行並修改 DOM:
dom.window.document.body.children.length === 2;

咱們再次強調只有在提供給jsdom的代碼是你已知道是安全的代碼時方可以使用它。若是您運行了任意用戶提供的或Internet上的不可信的Node.js代碼,可能會危及您的計算機。

假如你想經過<script src="">來執行外部腳本,你須要確保已經加載了它們。爲此,請添加選項resources:"usable" 以下所述

請注意,除非runScripts設置爲"dangerously",不然事件處理程序屬性(如<div onclick =「」>)也將不起做用。(可是,事件處理函數屬性,好比div.onclick = ...,將無視runScripts參數 而且會起做用)

若是您只是試圖從「外部」執行腳本,而不是經過<script>元素(和內聯事件處理程序)從內部運行「,則可使用runScripts: "outside-only"選項,該選項會啓用window.eval

const window = (new JSDOM(``, { runScripts: "outside-only" })).window;

window.eval(`document.body.innerHTML = "<p>Hello, world!</p>";`);
window.document.body.children.length === 1;

因爲性能緣由,默認狀況下會關閉此功能,但能夠安全啓用。

請注意,咱們強烈建議不要試圖經過將jsdom和Node全局環境混合在一塊兒(例如,經過執行global.window = dom.window)來「執行腳本」,而後在Node全局環境中執行腳本或測試代碼。相反,您應該像對待瀏覽器同樣對待jsdom,並使用window.evalrunScripts: "dangerously"來運行須要訪問jsdom環境內的DOM的全部腳本和測試。例如,這可能須要建立一個browserify包做爲<script>元素執行 - 就像在瀏覽器中同樣。

最後,對於高級用例,您可使用dom.runVMScript(腳本)方法,以下所述。

僞裝成一個視覺瀏覽器

jsdom沒有渲染可視內容的能力,而且默認狀況下會像無頭瀏覽器同樣工做。它經過API(如document.hidden)向網頁提供提示,代表其內容不可見。

pretendToBeVisual選項設置爲true時,jsdom會僞裝它正在呈現並顯示內容。它是這樣作的:

  • 更改document.hidden以返回false而不是true
  • 更改document.visibilityState以返回「visible」而不是「prerender」
  • 啓用window.requestAnimationFrame()window.cancelAnimationFrame()方法,不然不存在
const window = (new JSDOM(``, { pretendToBeVisual: true })).window;

window.requestAnimationFrame(timestamp => {
  console.log(timestamp > 0);
});

請注意,jsdom仍然不作任何佈局或渲染,所以這實際上只是僞裝爲可視化,而不是實現真正的可視化Web瀏覽器將實現的部分。

加載子資源

默認狀況下,jsdom不會加載任何子資源,如腳本,樣式表,圖像或iframe。若是您但願jsdom加載這些資源,則能夠傳遞resources: "usable"選項,該選項將加載全部可用資源。資源列表以下:

  • frame 和 iframe,經過 <frame><iframe>實現
  • 樣式,經過<link rel="stylesheet">
  • 腳本,經過<script>,可是前提是runScripts: "dangerously"設置了
  • 圖片,經過<img>,可是前提是canvas(或者 canvas-prebuilt) npm 包已安裝

將來,咱們計劃經過此選項提供更多的資源加載定製,但如今只提供的兩種模式:'default''usable'

虛擬控制檯

像網頁瀏覽器同樣,jsdom也具備「控制檯」的概念。經過在文檔內執行的腳本以及來自jsdom自己實現的信息和記錄會從頁面直接發送過來。咱們將用戶可控制的控制檯稱爲「虛擬控制檯」,以便將其與Node.js console API和頁面內部的window.console API區分開來。

默認狀況下,JSDOM構造函數將返回一個具備虛擬控制檯的實例,該虛擬控制檯將其全部輸出轉發到Node.js控制檯。爲了建立本身的虛擬控制檯並將其傳遞給jsdom,能夠經過執行下面代碼來覆蓋此默認值

const virtualConsole = new jsdom.VirtualConsole();
const dom = new JSDOM(``, { virtualConsole });

這樣的代碼將建立一個沒有任何行爲的虛擬控制檯。您能夠爲全部可能的控制檯方法添加事件偵聽器來爲其提供行爲:

virtualConsole.on("error", () => { ... });
virtualConsole.on("warn", () => { ... });
virtualConsole.on("info", () => { ... });
virtualConsole.on("dir", () => { ... });
// ... etc. See https://console.spec.whatwg.org/#logging

請注意,最好在調用 new JSDOM()以前設置這些事件偵聽器,由於在解析期間可能會發生錯誤或控制檯調用腳本錯誤。)

若是你只是想將虛擬控制檯輸出重定向到另外一個控制檯,好比默認的Node.js,你能夠這樣作

virtualConsole.sendTo(console);

還有一個特殊的事件,"jsdomError",它的觸發將經過錯誤對象來記錄jsdom自己的錯誤。這與錯誤消息在Web瀏覽器控制檯中的顯示方式相似,即便它們不是由console.error輸出的。到目前爲止,錯誤會按照下面的方式輸出:

  • 加載或解析子資源時出錯(腳本,樣式表,frames和iframe)
  • 不是由window onerror事件處理程序處理的腳本執行錯誤,它將會返回true或調用event.preventDefault()
  • 因爲調用jsdom沒有實現的方法而致使的錯誤,例如window.alert,兼容性的 web 瀏覽器都實現了這些方法

若是您使用sendTo(c)將錯誤發送給c,則默認狀況下,它將使用來自"jsdomError"事件的信息調用console.error。若是您但願保持事件與方法調用的嚴格的一對一映射,而且可能本身處理"jsdomError",那麼您能夠執行

virtualConsole.sendTo(c, { omitJSDOMErrors: true });

Cookie jars(存儲Cookie的容器)

像網頁瀏覽器同樣,jsdom也具備cookie jar的概念,存儲HTTP cookie 。在文檔的同一個域上一個URL,而且沒有標記爲HTTP only的cookies,能夠經過document.cookie API來訪問。此外,Cookie jar中的全部cookie都會影響子資源的http加載。

默認狀況下,JSDOM構造函數將返回一個帶有空cookie的實例。要建立本身的cookie jar並將其傳遞給jsdom,能夠經過如下代碼來覆蓋默認值

const cookieJar = new jsdom.CookieJar(store, options);
const dom = new JSDOM(``, { cookieJar });

若是您想要在多個jsdoms中共享同一個cookie jar,或者提早使用特定的值來填充cookie jar,這將很是有用。

Cookie jar包由tough-cookie包提供的。jsdom.CookieJar構造函數是tough-cookie cookie jar的子類,而且默認設置了looseMode:true選項,由於它更符合瀏覽器的行爲方式。若是您想本身使用tough-cookie的方法和類,則可使用jsdom.toughCookie模塊導出來訪問使用jsdom打包的tough-cookie模塊實例。

在解析以前進行干預

jsdom容許您在很早的時候介入建立jsdom:建立Window和Document對象以後,但在解析任何HTML並使用節點填充文檔以前

const dom = new JSDOM(`<p>Hello</p>`, {
  beforeParse(window) {
    window.document.childNodes.length === 0;
    window.someCoolAPI = () => { /* ... */ };
  }
});

若是您但願以某種方式修改環境,這尤爲有用,例如添加jsdom不支持的Web API的填充程序。

JSDOM object API

一旦你構建了一個JSDOM對象,它將具備如下有用的功能:

Properties

window屬性: window對象的key 從Window 對象檢索而來
virtualConsolecookieJar:能夠傳入或者使用默認值

經過serialize()序列化document

const dom = new JSDOM(`<!DOCTYPE html>hello`);

dom.serialize() === "<!DOCTYPE html><html><head></head><body>hello</body></html>";

// Contrast with:
dom.window.document.documentElement.outerHTML === "<html><head></head><body>hello</body></html>";

經過nodeLocation(node)獲取 dom 節點的源位置信息

nodeLocation()方法將查找DOM節點在源文檔中的位置,並返回節點的parse5位置信息

const dom = new JSDOM(
  `<p>Hello
    <img src="foo.jpg">
  </p>`,
  { includeNodeLocations: true }
);

const document = dom.window.document;
const bodyEl = document.body; // implicitly created
const pEl = document.querySelector("p");
const textNode = pEl.firstChild;
const imgEl = document.querySelector("img");

console.log(dom.nodeLocation(bodyEl));   // null; it's not in the source
console.log(dom.nodeLocation(pEl));      // { startOffset: 0, endOffset: 39, startTag: ..., endTag: ... }
console.log(dom.nodeLocation(textNode)); // { startOffset: 3, endOffset: 13 }
console.log(dom.nodeLocation(imgEl));    // { startOffset: 13, endOffset: 32 }

請注意,只有您設置了includeNodeLocations選項才能使用此功能;因爲性能緣由,節點位置默認爲關閉。

使用runVMScript(script)運行vm建立的腳本

Node.js的內置vm模塊容許您建立Script實例,這些腳本實例能夠提早編譯,而後在給定的「VM上下文」上運行屢次。在這個場景背後,jsdom Window是一個肯定的VM上下文。要訪問此功能,請使用runVMScript()方法:

const { Script } = require("vm");

const dom = new JSDOM(``, { runScripts: "outside-only" });
const s = new Script(`
  if (!this.ran) {
    this.ran = 0;
  }

  ++this.ran;
`);

dom.runVMScript(s);
dom.runVMScript(s);
dom.runVMScript(s);

dom.window.ran === 3;

這是高級功能,除非您有特殊的需求,不然咱們建議堅持使用普通的DOM API(如window.eval()或document.createElement(「script」))。

經過reconfigure(settings)從新配置jsdom

window.top屬性在規範中被標記爲Unforgeable,這意味着它是一個不可配置的私有屬性,所以在jsdom內運行的普通代碼是不能覆蓋或遮擋它的,即便使用Object.defineProperty

一樣,目前在jsdom中是不可以處理navigation相關信息的(好比設置window.location.href ="https://example.com/");這樣作會致使虛擬控制檯發出"jsdomError",說明此功能未實現,而且沒有任何變化,也將不會有新的WindowDocument對象,而且現有window.location對象仍保持當前全部相同的屬性值。

可是,若是您從 jsdom 窗口以外進行演示,例如在一些建立jsdoms的測試框架中,可使用特殊的reconfigure()方法覆蓋其中的一個或兩個:

const dom = new JSDOM();

dom.window.top === dom.window;
dom.window.location.href === "about:blank";

dom.reconfigure({ windowTop: myFakeTopForTesting, url: "https://example.com/" });

dom.window.top === myFakeTopForTesting;
dom.window.location.href === "https://example.com/";

請注意,更改jsdom的URL將影響全部返回當前 document URL的API,例如window.locationdocument.URL`和document.documentURI,以及文檔中相對URL的解析以及同源檢查和提取子資源時使用的引用。可是,它不會執行導航到該URL的內容;DOM的內容將保持不變,而且不會建立WindowDocument`等新的實例。

便捷的 APIs

fromURL()

除了JSDOM構造函數自己以外,jsdom還提供了一個返回 Promise 的工廠方法,用於經過URL構建一個jsdom實例

JSDOM.fromURL("https://example.com/", options).then(dom => {
  console.log(dom.serialize());
});

若是URL有效且請求成功,則onFullfilled回調執行並返回JSDOM實例。任何URL重定向都將遵循其最終目的地。

fromURL()提供的參數選項與提供給JSDOM構造函數的選項相似,但具備如下額外的限制和後果:

  • urlcontentType 參數不能被提供
  • referrer 選項用做初始請求的HTTP Referer請求頭
  • userAgent 選項用做任何請求的HTTP User-Agent請求頭
  • 生成的jsdom的urlcontentTypereferrer是 由 http response來決定
  • 任何經過HTTP Set-Cookie響應頭設置的cookie都存儲在jsdom的cookie jar中。一樣,已提供的cookie jar中的任何cookie都會做爲HTTP Cookie請求標頭髮送。

初始的請求並不能無限定製到像request npm 包同樣的程度;fromURL()旨在爲大多數狀況提供便利的API。若是您須要更好地控制初始請求,您應該本身執行它,而後手動使用JSDOM構造函數。

fromFile()

fromURL()相似,jsdom還提供了一個fromFile()工廠方法,用於從文件名構建jsdom

JSDOM.fromFile("stuff.html", options).then(dom => {
  console.log(dom.serialize());
});

若是能夠打開給定的文件,則onFullfilled回調執行並返回JSDOM實例。和Node.js API同樣,文件名是相對於當前工做目錄的。

fromFile()提供的選項與提供給JSDOM構造函數的選項類似,但具備如下額外的默認值:

  • url選項將默認爲給定文件名相對應的文件URL,而不是"about:blank"
  • 假如給定的文件名是以.xhtml或者.xml爲後綴的話,contentType選項默認爲"application/xhtml+xml";反之爲"text/html"

fragment()

對於最簡單的狀況,你可能不須要一個完整的JSDOM實例及其全部相關的功能。您甚至可能不須要WindowDocument!相反,你只須要解析一些HTML片斷,並得到一個你能夠操做的DOM對象。爲此,咱們提供了fragment(),它能夠從給定的字符串中建立一個DocumentFragment

const frag = JSDOM.fragment(`<p>Hello</p><p><strong>Hi!</strong>`);

frag.childNodes.length === 2;
frag.querySelector("strong").textContent = "Why hello there!";
// etc.

fragDocumentFragment的實例對象,其內容是經過提供的字符串解析建立的。解析是經過使用<template>元素完成的,所以您能夠在其中包含任何元素(包括具備奇怪解析規則的元素,如<td>)。

fragment()工廠函數的全部調用結果的DocumentFragments實例都會共享相同的DocumentWindow。這容許屢次調用fragment()而沒有額外的開銷。但這也意味着對fragment()的調用不能用任何選項自定義。

請注意,對DocumentFragments的序列化並不像使用JSDOM對象那樣容易。若是你須要序列化你的DOM,你應該直接使用JSDOM構造函數。但對於包含單個元素的片斷的特殊狀況,經過常規方法就很容易作到。

const frag = JSDOM.fragment(`<p>Hello</p>`);
console.log(frag.firstChild.outerHTML); // logs "<p>Hello</p>"

其餘值得注意的功能

支持 Canvas

jsdom支持使用canvascanvas-prebuilt包來擴展任何使用canvas API的<canvas>元素。爲了作到這一點,您須要將canvas做爲依賴項加入到您的項目中,和 jsdom包並列。若是jsdom能夠找到canvas包,它將使用它,可是若是它不存在,那麼<canvas>元素的行爲就像<div>同樣。

編碼嗅探

除了提供一個字符串外,JSDOM構造函數還支持Node.js Buffer或標準JavaScript二進制數據類型(如ArrayBuffer,Uint8Array,DataView等)的形式提供二進制數據。當完成後,jsdom將從提供的字節進行嗅探編碼,就像瀏覽器掃描<meta charset>標籤同樣。

這種編碼嗅探也適用於JSDOM.fromFile()JSDOM.fromURL()。在後一種狀況下,就像在瀏覽器中同樣,任何與response響應一塊兒發送的Content-Type頭信息優先級更高。

請注意,在許多狀況下,提供字節這種方式可能比提供字符串更好。例如,若是您試圖使用Node.js的buffer.toString('utf-8')API,則Node.js將不會去除任何前導BOM。若是您將此字符串提供給jsdom,它會逐字解釋,從而使BOM保持不變。但jsdom的二進制數據解碼代碼將剝離前導的BOM,就像瀏覽器同樣;在這種狀況下,直接提供buffer將會獲得想要的結果。

關閉一個jsdom

jsdom中定義的定時器(經過window.setTimeoutwindow.setInterval設置)將在window上下文中執行代碼。因爲進程在不活躍的狀況下沒法執行將來的定時器代碼,因此卓越的jsdom定時器將保持您的Node.js進程處於活動狀態。一樣,對象不活躍的狀況下也沒有辦法在對象的上下文中執行代碼,卓越的jsdom定時器將阻止垃圾回收調度它們的window。

若是你想確保關閉jsdom窗口,使用window.close(),它將終止全部正在運行的定時器(而且還會刪除 windowdocument上的任何事件監聽器)。

在Web瀏覽器中運行jsdom

使用browserify模塊,jsdom某些方面也支持在Web瀏覽器中運行。也就是說,在Web瀏覽器中,您可使用被browserify模塊編譯過的jsdom去建立徹底獨立的普通JavaScript對象集,其外觀和行爲與瀏覽器的現有DOM對象很是類似,但徹底獨立於它們,也就是"虛擬DOM"!

jsdom的主要目標對象仍然是Node.js,所以咱們使用僅存在於最新Node.js版本(即Node.js v6 +)中的語言特性功能。所以,在舊版瀏覽器可能沒法正常工做。(即便編譯也不會有多大幫助:咱們計劃在jsdom v10.x的整個過程當中普遍使用Proxy。)

值得注意的是,jsdom在web worker中能很好的運行。項目的開發者@lawnsea使這一功能點成爲可能,他發表了一篇關於他的項目的論文,該論文就使用了這種能力。

在Web瀏覽器中運行jsdom時,並不是全部的工做都完美。有些狀況下,這是因爲基礎的條件限制(好比沒有文件系統訪問),但有些狀況下也是由於咱們沒有花足夠的時間去進行適當的小調整。歡迎你們來提BUG。

使用Chrome Devtools調試DOM

從Node.js v6開始,您可使用Chrome Devtools來調試程序。請參閱官方文檔瞭解如何使用。

默認狀況下,jsdom元素在控制檯中被格式化爲普通的舊JS對象。爲了便於調試,可使用jsdom-devtools-formatter,它可讓你像真正的DOM元素同樣調試它們。

注意事項

異步腳本加載

使用jsdom時,開發者在加載異步腳本時常常遇到麻煩。許多頁面異步加載腳本,但沒法分辨腳本何時完成,所以沒法知道什麼時候是運行代碼並檢查生成的DOM結構的好時機。這是一個基本的限制;咱們沒法預測網頁上的哪些腳本會作什麼,所以沒法告訴您腳本什麼時候加載完畢。

這個問題能夠經過幾種方法來解決。若是您能控制頁面邏輯,最好的方法是使用腳本加載器提供的機制來檢測什麼時候加載完成。例如,若是您使用像RequireJS這樣的模塊加載器,代碼可能以下所示:

// On the Node.js side:
const window = (new JSDOM(...)).window;
window.onModulesLoaded = () => {
  console.log("ready to roll!");
};
<!-- Inside the HTML you supply to jsdom -->
<script>
requirejs(["entry-module"], () => {
  window.onModulesLoaded();
});
</script>

若是您不能控制該頁面,則能夠嘗試其餘解決方法,例如輪詢檢查特定元素是否存在。有關更多詳細信息,請查看#640中的討論,尤爲是@ matthewkastor深入看法

共享的構造函數和原型

目前,對於大多數Web平臺API,jsdom在多個看似獨立的jsdoms之間共享相同的類定義。這將意味着,可能會出現如下狀況

const dom1 = new JSDOM();
const dom2 = new JSDOM();

dom1.window.Element.prototype.expando = "blah";
console.log(dom2.window.document.createElement("frameset").expando); // logs "blah"

這主要是出於性能和內存的緣由:若是在Web平臺上每次建立jsdom時,建立全部類的單獨副本,開銷將會至關昂貴。

儘管如此,咱們仍然有興趣在有一天提供一個選項配置來建立一個「獨立」的jsdom,但要犧牲一些性能。

新API中缺失的功能

與v9.x以前的舊版jsdom API相比,新API顯然缺乏對資源加載的精細控制。先前版本的jsdom容許您設置request時使用的選項(既能夠用於初始請求,也能夠用於舊版本的JSDOM.fromURL()和子資源請求)。他們還容許您控制請求哪些子資源並將其應用於主文檔,以便您能夠下載樣式表,但不下載腳本文件。最後,他們提供了一個可定製的資源加載器,能夠攔截任何傳出的請求並用徹底合成的response 響應來結束。

以上這些功能還沒有在新的jsdom API中實現,儘管咱們也但願儘快將它們添加回來,但不幸的是,這須要至關大的幕後工做去實施。

同時,請隨時使用舊的jsdom API來訪問此功能。它一直處於支持和維護中,但它不會得到新功能。舊的文檔位於lib/old-api.md中。

未實現的Web平臺部分

目前jsdom中有不少缺失的API,儘管咱們也想要在jsdom中添加新的功能並保持最新的Web規範。請隨時爲缺失的任何內容提交issue,但咱們是一個很小而且忙碌的團隊,所以你們一塊兒來提交 pull request可能會更好。

除了咱們還沒有擁有的功能以外,還有兩個主要功能目前超出了jsdom的範圍。這些是:

  • Navigation:在點擊連接或賦值location.href或相似操做時能夠更改全局對象和全部其餘的對象。
  • Layout:計算CSS元素的視覺佈局的能力,這會影響諸如getBoundingClientRects()或者諸如offsetTop之類的屬性

目前,jsdom對某些功能的某些方面具備虛擬行爲,例如操做navigation 時向虛擬控制檯發送「未實現的」"jsdomError",或者爲許多與佈局相關的屬性返回0。您一般能夠在代碼中解決這些限制,例如經過在爬網過程當中爲每一個頁面建立新的JSDOM實例,或使用Object.defineProperty更改各類與佈局相關的getter和方法的返回值

請注意,相同領域中的其餘工具(如PhantomJS)確實支持這些功能。在wiki上,咱們有關於jsdom vs. PhantomJS的更完整的比較介紹。

獲取幫助

若是您須要jsdom的幫助,請隨時使用如下任何方式:

  • 郵件組(問題最好以"how do i"的形式)
  • 報iusse(最好用BUG 報告)
  • IRC頻道:#jsdom on freenode

特別聲明

以上文檔翻譯自開源項目 jsdom,若有翻譯錯誤,歡迎指正。

jsdom 原文連接

jsdom 項目連接

jsdom 中文翻譯wiki連接

原文博客地址

相關文章
相關標籤/搜索