WebView
通過 Bun 控制無頭瀏覽器,用於自動化、測試和抓取 — 在 macOS 上零相依;其餘平臺到處都是 Chrome DevTools Protocol
Bun.WebView 是內建在執行環境中的無頭瀏覽器。使用它來載入頁面、在其中執行 JavaScript、模擬真實使用者輸入,並擷取螢幕截圖 — 不需要 Puppeteer、Playwright,也不需要單獨下載瀏覽器。
await using view = new Bun.WebView();
await view.navigate("https://example.com");
await view.click("a[href]"); // 等待連結變為可點選
const title = await view.evaluate("document.title");
await Bun.write("page.png", await view.screenshot());
在 macOS 上,Bun.WebView 使用系統的 WKWebView — 無需安裝任何東西。在 Linux 和 Windows 上,它會通過 Chrome DevTools Protocol 驅動已安裝的 Chrome、Chromium、Edge 或 Brave;在 Windows 上,預裝的 Edge 就足夠了。
每個檢視都會在單獨的渲染器行程中執行其頁面。所有輸入方法(click、type、press、scroll)都會分發原生瀏覽器事件,因此頁面會看到 isTrusted: true — 與真實使用者一致。
建立檢視
const view = new Bun.WebView({
width: 1280, // 視口寬度(CSS 畫素,1-16384,預設 800)
height: 720, // 視口高度(CSS 畫素,1-16384,預設 600)
url: "https://bun.sh", // 可選:立即開始導航
});
建構函式是同步的——它會立即傳回,並在後臺啟動瀏覽器子行程。你 await 的第一個操作(例如 navigate() 或 evaluate())會等待瀏覽器準備就緒。
如果傳入 url,檢視會在建構函式傳回前開始導航,效果與在下一行呼叫 view.navigate(url) 相同。不同之處在於:建構函式會將導航的 promise 保留在內部,因此失敗時不會產生拒絕。設定 onNavigationFailed 以便觀察導航失敗。
使用 using 的自動清理
Bun.WebView 實現了 Symbol.dispose 和 Symbol.asyncDispose,因此你可以使用 using 或 await using,當檢視超出作用域時自動關閉:
{
await using view = new Bun.WebView();
await view.navigate("https://example.com");
// ...
} // 這裡會自動呼叫 view.close()
持久化儲存
預設情況下,每個檢視使用短暫的記憶體儲存 — cookies、localStorage、IndexedDB 和快取都會在檢視關閉時丟棄。要在多次執行之間持久化狀態,請傳入目錄:
const view = new Bun.WebView({
dataStore: { directory: "./browser-profile" },
});
共享同一個 directory 的檢視會共享 cookies 和儲存。傳入 dataStore: "ephemeral"(預設值)以顯式回到記憶體儲存。
後端
Bun.WebView 支援兩種渲染引擎。預設取決於你的平臺:
| 後端 | 引擎 | 平臺 | 要求 |
|---|---|---|---|
"webkit" | WKWebView | 僅 macOS | 無 — 使用系統的 WebKit.framework |
"chrome" | Blink | macOS / Linux / Windows | 已安裝 Chrome、Chromium、Edge 或 Brave(或 Playwright 的 chrome-headless-shell) |
在 macOS 上,預設後端是 "webkit";其他平臺預設使用 "chrome"。在非 macOS 平臺請求 backend: "webkit" 會丟擲異常。"chrome" 後端每個行程驅動一個瀏覽器,且只能從主執行緒使用;在 Worker 中構造它會丟擲異常。
// 在 macOS 上強制使用 Chrome
const view = new Bun.WebView({ backend: "chrome" });
WebKit 後端如何工作
Bun 會生成一個輕量級宿主子行程(即 bun 二進位制檔案本身,以特殊模式重新執行),由它在主執行緒上管理 WKWebView。你的 Bun 行程通過 Unix socket 使用緊湊的二進位制協議與其通訊。Bun 只生成一次宿主行程,你的程式中的每個 "webkit" 檢視都會共用它。
Chrome 後端如何工作
Bun 要麼連線到一個已經執行的 Chrome(通過 WebSocket),要麼生成一個無頭 Chrome 子行程,並通過管道與它通訊(--remote-debugging-pipe)。無論哪種方式,通訊都使用 Chrome DevTools Protocol。
Bun 每個行程只生成(或連線)一次 Chrome。每個 new Bun.WebView({ backend: "chrome" }) 都會在該 Chrome 例項中使用 Target.createTarget 建立一個新標籤頁。
查詢 Chrome 執行檔
當 Bun 需要生成 Chrome 時,它會按以下順序搜尋:
- 你在
backend: { type: "chrome", path: "..." }中傳入的path BUN_CHROME_PATH環境變數$PATH(google-chrome-stable、google-chrome、chromium-browser、chromium、brave-browser、microsoft-edge、chrome;在 Windows 上為chrome、chromium、brave、msedge)- 標準安裝位置(
/Applications/Google Chrome.app、~/Applications/...、/usr/bin/...、/snap/bin/...;在 Windows 上為%ProgramFiles%、%ProgramFiles(x86)%和%LOCALAPPDATA%下的Application\*.exe目錄) - Playwright 的快取(
~/Library/Caches/ms-playwright、~/.cache/ms-playwright或%LOCALAPPDATA%\ms-playwright)中的chrome-headless-shell
如果 Bun 找不到 Chrome,建構函式會丟擲異常。
連線到已在執行的 Chrome
預設情況下,在生成瀏覽器之前,Bun 會從標準設定檔目錄讀取 DevToolsActivePort 檔案,以檢查是否已經有啟用了遠端除錯的 Chrome 系瀏覽器在執行。如果找到,Bun 會通過 WebSocket 連線到該瀏覽器,而不是生成新瀏覽器 — 你的檢視會作為標籤頁在現有瀏覽器中開啟。
要在執行中的 Chrome 中啟用遠端除錯,請訪問 chrome://inspect/#remote-debugging 並開啟開關,或者使用 --remote-debugging-port=9222 啟動 Chrome。使用 chrome://inspect 開關時,Chrome 會在每次建立新連線時請求許可權。
要顯式控制這一行為,請使用 backend 的物件形式:
// 總是生成一個新的無頭 Chrome;永遠不自動連線
new Bun.WebView({
backend: { type: "chrome", url: false },
});
// 連線到特定的 DevTools WebSocket URL
new Bun.WebView({
backend: {
type: "chrome",
url: "ws://127.0.0.1:9222/devtools/browser/abc123...",
},
});
如果自動探測發現過期的 DevToolsActivePort 檔案(Chrome 崩潰或重啟),WebSocket 連線將失敗,並且 Bun 會透明地回退到生成自己的 Chrome。顯式指定 url: "ws://..." 不會回退 — 連線失敗會直接丟擲異常。
啟動引數
生成時,Bun 會傳入一組最小的引數:
--user-data-dir=<temp> --remote-debugging-pipe --headless --no-first-run
--no-default-browser-check --disable-gpu --disable-extensions
--disable-background-networking --disable-background-timer-throttling
--disable-backgrounding-occluded-windows --disable-renderer-backgrounding
--disable-ipc-flooding-protection --no-startup-window
用 argv 把你自己的引數追加進去 — Chrome 處理重複開關時採用“最後生效”,因此你可以覆蓋任意預設值:
new Bun.WebView({
backend: {
type: "chrome",
argv: ["--headless=new", "--lang=ja-JP", "--window-size=1920,1080"],
},
});
子行程輸出
瀏覽器子行程的 stdout/stderr 預設會被靜默處理。尤其是 Chrome,其 stderr 輸出十分嘈雜(字型設定警告、GCM 註冊、更新程式檢查)。要檢視這些輸出 — 在 Chrome 靜默崩潰時很有用 — 請傳入 "inherit":
new Bun.WebView({
backend: { type: "chrome", stderr: "inherit", stdout: "inherit" },
});
"webkit" 後端也接受相同的 stdout/stderr 選項。
導航
await view.navigate("https://example.com");
await view.navigate("data:text/html,<h1>hello</h1>");
await view.navigate("file:///path/to/index.html");
當主框架的 load 事件觸發時,navigate() 才會解析完成。解析完成後,view.url 和 view.title 會反映新頁面,且 view.loading 為 false。
如果導航失敗(DNS 失敗、連線被拒絕、URL 無效),該 promise 會以描述失敗原因的 Error 形式拒絕。
每個檢視在任一時刻只能進行一個正在進行的導航。若在另一個 navigate() 仍待處理時再次呼叫 navigate(),會同步丟擲 ERR_INVALID_STATE。
歷史記錄
await view.goBack(); // 類似瀏覽器的傳回按鈕
await view.goForward(); // 類似瀏覽器的前進按鈕
await view.reload(); // 重新載入當前頁面
在歷史記錄的起點(或終點)呼叫 goBack()(或 goForward())會直接解析為 undefined,不進行導航 — 不會拒絕。
導航回撥
設定 onNavigated 和 onNavigationFailed 來觀察每一次導航,包括頁面自身觸發的導航(點選連結、location.href = ...、重定向)以及由 reload()/goBack()/goForward() 觸發的導航:
view.onNavigated = (url, title) => {
console.log("Loaded", url);
};
view.onNavigationFailed = error => {
console.error("Navigation failed:", error.message);
};
這些回撥會在對應的 navigate() promise 完成(settle)之前觸發,因此當你 await view.navigate(...) 傳回時,你的回撥已經執行過了。設定為 null 可移除。
計算 JavaScript
在頁面的主框架中執行一個表示式,並把結果作為原生 JavaScript 值傳回:
const title = await view.evaluate("document.title");
const items = await view.evaluate("[...document.querySelectorAll('li')].map(li => li.textContent)");
const user = await view.evaluate("({ name: 'bun', ok: true })");
Bun 會將指令碼包裝為 await (<your script>),因此:
- 它必須是一個表示式,而不是語句序列。若要執行多個語句,請將它們包裝在 IIFE 中:
evaluate("(() => { let x = foo(); return x + 1 })()")。 - 如果計算結果是一個
Promise,evaluate()會等待該 promise,並傳回其解析後的值。
結果會在頁面側通過 JSON.stringify,在 Bun 側通過 JSON.parse 來往返傳遞。陣列和普通物件會以真實結構傳回;undefined、函式和 symbol 會解析為 undefined;迴圈引用會導致拒絕。
await view.evaluate("42"); // 42
await view.evaluate("[1, 2, 3]"); // [1, 2, 3]
await view.evaluate("undefined"); // undefined
await view.evaluate("() => 1"); // undefined(函式不會序列化)
await view.evaluate("fetch('/api').then(r => r.json())"); // 已等待
如果指令碼丟擲異常(或傳回被拒絕的 promise),evaluate() 會拒絕,並把訊息作為頁面側異常資訊的一部分傳回一個 Error。
每個檢視在任一時刻只能進行一個正在進行的 evaluate();第二個並行呼叫會同步丟擲 ERR_INVALID_STATE。
截圖
把當前視口捕獲成圖片:
const png = await view.screenshot();
await Bun.write("page.png", png);
圖片格式
await view.screenshot({ format: "png" }); // 無損(預設)
await view.screenshot({ format: "jpeg", quality: 90 }); // 有損,quality 0-100(預設 80)
await view.screenshot({ format: "webp", quality: 75 }); // 僅 Chrome 後端
PNG 會忽略 quality。"webp" 只在 backend: "chrome" 時可用 — WebKit 後端會丟擲異常。
傳回型別
encoding 選項控制 Bun 如何傳回圖片位元組:
encoding | 傳回內容 | 說明 |
|---|---|---|
"blob" (預設) | Blob | MIME 型別自動設定。WebKit 上基於 mmap 的零複製。可與 Bun.write()、new Response() 一起使用 |
"buffer" | Buffer | Node Buffer。WebKit 上基於 mmap 的零複製 |
"base64" | string | Base64 編碼。Chrome 上無需解碼(CDP 原生傳回 base64) |
"shmem" | { name: string, size: number } | POSIX 共享記憶體段名稱。呼叫方負責 shm_unlink。Windows 不支援 |
const buf = await view.screenshot({ encoding: "buffer" });
console.log(buf[0] === 0x89); // PNG 魔術位元組
const b64 = await view.screenshot({ encoding: "base64" });
console.log(`<img src="data:image/png;base64,${b64}">`);
終端圖形的共享記憶體
encoding: "shmem" 專為 Kitty 的終端圖形協議 t=s 傳輸模式設計。Bun 會將圖片寫入 POSIX 共享記憶體段並傳回其名稱。終端會直接讀取它,並在完成後取消連結。無需通過管道複製。
const { name, size } = await view.screenshot({ encoding: "shmem" });
process.stdout.write(`\x1b_Gf=100,t=s,a=T,S=${size};${btoa(name)}\x1b\\`);
// Kitty 從共享記憶體讀取 PNG 並取消連結該段
在 WebKit 上,shm 名稱看起來像 /bun-webview-<pid>-<seq>;在 Chrome 上是 /bun-chrome-<pid>-<seq>。如果你請求 "shmem",但沒有把名稱交給某個會執行 shm_unlink 的邏輯,那麼共享記憶體段會在你的行程退出前一直洩漏。
輸入模擬
所有輸入方法都會分發原生瀏覽器事件。頁面會收到 isTrusted: true 的 pointerdown/mousedown/keydown/wheel 事件。CSS :active 和 :hover 狀態會生效。預設操作(表單提交、連結導航、文本選擇)會與使用者實際操作時完全一樣地觸發。
點選
在視口座標處點選:
await view.click(150, 200);
await view.click(150, 200, { button: "right" });
await view.click(150, 200, { clickCount: 2 }); // 雙擊
await view.click(150, 200, { modifiers: ["Shift", "Meta"] });
promise 會在頁面處理完完整的 mousedown → mouseup → click 序列(包括任何 JavaScript 處理程序)後解析。無需輪詢 — 後續的 evaluate() 可以看到結果。
通過選擇器點選
傳入 CSS 選擇器而不是座標,Bun 會等待元素變為可操作,然後點選其中心:
await view.click("#submit");
await view.click("button.primary", { timeout: 5000 });
當元素滿足以下條件時,它才是可操作的:
- 存在於 DOM 中
- 擁有非零的邊界框
- 位於視口內
- 已保持穩定(在連續兩幀動畫中邊界框未改變)
- 在其中心點處是最上層元素(沒有被覆蓋物遮擋)
該檢查會在頁面側以 requestAnimationFrame 的頻率執行。如果該元素在 timeout 毫秒內始終未變為可操作(預設 30000),promise 會以類似 timeout waiting for '#submit' to be actionable 的錯誤拒絕。
Bun 會將選擇器作為資料傳遞,而不是將其插入指令碼中,因此包含引號或 JavaScript 語法的選擇器也是安全的。
輸入文本
把文本插入到當前聚焦的元素中:
await view.click("input#email"); // 先聚焦
await view.type("hello@example.com");
type() 使用瀏覽器的 InsertText 編輯命令(與貼上使用同一路徑),而不是逐字元的按鍵模擬。它會觸發帶 isTrusted: true 的 beforeinput/input 事件,但不會觸發 keydown/keyup 事件。不會進行 IME 處理,也不會進行智慧引號替換 — 文本會被按原樣精確寫入。
按下按鍵
await view.press("Enter");
await view.press("Escape");
await view.press("ArrowDown");
await view.press("a", { modifiers: ["Meta"] }); // Cmd+A / Ctrl+A
命名的虛擬按鍵:Enter、Tab、Space、Backspace、Delete、Escape、ArrowLeft、ArrowRight、ArrowUp、ArrowDown、Home、End、PageUp、PageDown。
任意單個字元(例如 "a")與 modifiers 組合使用時,會發送鍵盤組合鍵。
在 WebKit 後端上,大多數命名按鍵(不帶修飾鍵)會對映到 DeleteBackward、MoveLeft 和 InsertNewline 等編輯命令,並在頁面應用這些命令後解析。Escape、Space 和帶有修飾鍵的任何按鍵都會回退到原始的 keydown/keyup 事件。這些按鍵會觸發頁面可觀察到的 keydown,但沒有完成屏障。如果需要觀察結果,請接著呼叫 evaluate()。
修飾鍵名稱:"Shift"、"Control"(或 "Ctrl")、"Alt"(或 "Option")、"Meta"(或 "Cmd" / "Command")。
滾動
按畫素增量滾動 — 在視口中心觸發一個原生 wheel 事件:
await view.scroll(0, 500); // 向下滾動 500px
await view.scroll(-100, 0); // 向左滾動 100px
正的 dy 會向下滾動(內容向上移動),與 window.scrollBy 一致。如果視口中心下方有可滾動元素,它會接收到 wheel 事件,而不是整個文件。
通過選擇器把元素滾入視野:
await view.scrollTo("#footer"); // 居中顯示(預設)
await view.scrollTo("#hero", { block: "start" }); // 讓元素頂部對齊視口頂部
await view.scrollTo(".card", { block: "nearest" }); // 最小滾動
scrollTo() 會以 requestAnimationFrame 的頻率等待元素存在,然後呼叫 element.scrollIntoView({ block, behavior: "instant" })。它會滾動所有可滾動祖先,而不僅僅是文件。預設 timeout 為 30000 ms。
調整大小
await view.resize(1920, 1080);
寬度和高度分別必須在 1 到 16384 之間。
控制台捕獲
通過在建構函式中傳入 console 選項,把頁面側的 console.* 呼叫轉發到你的 Bun 行程。
映象到 Bun 的控制台
傳入 globalThis.console(實際物件,按引用傳遞)。頁面側的 console.log("hi") 會使用 Bun 的格式化程式將 hi 列印到 stdout,console.error 則會輸出到 stderr。此路徑通過 Bun 的控制台實現直接分發,不會產生每次呼叫都要承擔的 JavaScript 開銷。
const view = new Bun.WebView({
console: globalThis.console,
});
自定義處理器
傳入一個函式來接收每次呼叫:
const view = new Bun.WebView({
console: (type, ...args) => {
// type 是 "log" | "warn" | "error" | "info" | "debug" | ...
if (type === "error") reportError(args);
},
});
原始引數(字串、數字、布林值、null、undefined)會解包為它們的原始值。物件引數會以序列化描述符的形式到達:
- Chrome 後端:原始的 CDP
RemoteObject— 一個包含type、className、description,以及(在可用時)preview.properties陣列的物件。 - WebKit 後端:物件經過
JSON.stringify往返後的結果。函式、迴圈引用以及其他不可序列化值會回退為String(...)的強制轉換。
如果你沒有傳入 console,Bun 會丟棄頁面側的控制台輸出。
原始 Chrome DevTools Protocol
當使用 backend: "chrome" 時,如果高層 API 沒有覆蓋你想要的能力,你可以直接切換到原始的 CDP 命令。
傳送命令
const view = new Bun.WebView({ backend: "chrome" });
await view.navigate("https://example.com"); // 必需:設定 CDP 會話
await view.cdp("Emulation.setUserAgentOverride", {
userAgent: "MyBot/1.0",
});
const { root } = await view.cdp("DOM.getDocument");
const { nodeId } = await view.cdp("DOM.querySelector", {
nodeId: root.nodeId,
selector: "input[name=q]",
});
await view.cdp("DOM.focus", { nodeId });
cdp(method, params?) 會傳回 CDP 響應中的 result 物件。如果 Chrome 傳回錯誤(未知方法、引數錯誤),該 promise 會以 error.message 拒絕。
命令會被限定在此檢視的會話範圍內(目標是此標籤頁)。在呼叫 cdp() 之前至少要 await navigate(...) 一次 — 第一次導航會建立會話。若在那之前呼叫 cdp() 會丟擲 ERR_INVALID_STATE。
params 必須是可 JSON 序列化的物件;對於不帶引數的命令可省略。每個檢視同一時刻最多隻能有一個 cdp() 呼叫正在進行。
訂閱事件
Bun.WebView 擴充套件了 EventTarget。使用 Chrome 後端時,檢視會將 CDP 事件作為 DOM 事件分發,其 type 為 CDP 方法名稱,data 為解析後的 params 物件:
await view.navigate("about:blank");
await view.cdp("Network.enable"); // 僅 Chrome:只有啟用了域才會發出事件
view.addEventListener("Network.responseReceived", event => {
console.log(event.data.response.status, event.data.response.url);
});
await view.navigate("https://example.com");
對於沒有註冊監聽器的事件,Bun 會在解析其 JSON params 之前就將其丟棄,因此如果你只監聽一兩種事件型別,啟用像 Network 這樣的高頻事件域也不會造成開銷。
在 WebKit 後端上,cdp() 會丟擲 ERR_METHOD_NOT_IMPLEMENTED — 沒有 DevTools Protocol 的橋接。EventTarget 介面仍然可用於你自己對 dispatchEvent() 的呼叫。
生命週期
關閉檢視
view.close();
關閉操作是同步且冪等的。它會銷燬頁面的渲染器行程,以 Error("WebView closed") 拒絕該檢視上所有待處理的 promise,並使之後的每次方法呼叫都丟擲 ERR_INVALID_STATE。這些拒絕會被標記為已處理:你持有的 promise 仍可以捕獲到拒絕,但沒有被任何物件持有的待處理操作不會觸發 unhandledRejection。
view[Symbol.dispose] 和 view[Symbol.asyncDispose] 都指向 close(),所以 using / await using 可以正常工作。
殺死所有瀏覽器
Bun.WebView.closeAll();
強制終止(SIGKILL)所有瀏覽器子行程(包括 Chrome 子行程和 WebKit 宿主子行程)。每個檢視上的待處理 promise 會在下一次事件迴圈 tick 時拒絕。之後的 new Bun.WebView() 呼叫會在需要時重新生成。
Bun 會在行程退出時自動呼叫它,因此瀏覽器子行程不會在你的指令碼之外存活。
事件迴圈行為
瀏覽器子行程本身不會讓 Bun 的事件迴圈保持執行。開啟的 WebView 僅會在存在待處理操作(例如尚未完成的 navigate() 或 evaluate())時讓行程保持執行。一旦你關閉最後一個檢視,或最後一個待處理操作完成,Bun 就會自然退出。
子行程死亡
如果瀏覽器子行程意外死亡(崩潰、被 OOM-kill、SIGKILL),每個檢視上所有待處理的 promise 都會以描述其死亡原因的錯誤拒絕("Chrome killed by signal 9"、"WebView host process died")。對這些檢視進行後續操作會丟擲異常。
並行模型
每個檢視都有少量用於並行的獨立“操作槽位”。同一種操作在任一時刻最多隻有一個在執行:
- 一個
navigate()(在 Chrome 後端與reload()/goBack()/goForward()共享) - 一個
evaluate() - 一個
screenshot() - 一個
cdp()(僅 Chrome) - 一個“簡單”操作 —
click()、type()、press()、scroll()、scrollTo()、resize()(以及 WebKit 後端的reload()/goBack()/goForward())共享此槽位
在操作槽位被佔用時啟動第二個操作會同步丟擲 ERR_INVALID_STATE — 它不會排隊。實際上,請對每次呼叫使用 await。
不同檢視之間的操作完全獨立,並會並行執行 — 每個檢視都有自己的渲染器行程。
參考
new Bun.WebView(options?)
| 選項 | 型別 | 預設值 | 描述 |
|---|---|---|---|
width | number | 800 | 視口寬度(CSS 畫素)。範圍 1-16384。 |
height | number | 600 | 視口高度(CSS 畫素)。範圍 1-16384。 |
url | string | — | 立即開始導航到該 URL。 |
headless | boolean | true | 僅實現 true;false 會丟擲異常。 |
backend | "webkit" | "chrome" | object | macOS 為 "webkit",其他為 "chrome" | 渲染引擎。 |
console | typeof console | (type, ...args) => void | — | 捕獲頁面側的 console.* 呼叫。見 控制台捕獲。 |
dataStore | "ephemeral" | { directory: string } | "ephemeral" | cookies / localStorage / IndexedDB 的儲存。見 持久化儲存。 |
backend 物件形式
| 選項 | 型別 | 描述 |
|---|---|---|
type | "chrome" | "webkit" | 必填。 使用哪個引擎。 |
path | string | (僅限 chrome)Chrome/Chromium 執行檔的路徑。強制進入生成模式。 |
argv | string[] | (僅限 chrome)額外的啟動引數,會在預設引數之後追加。強制進入生成模式。 |
url | string | false | (僅限 chrome)現有 Chrome 的 DevTools 端點 ws:// URL;或傳 false 跳過自動探測並始終生成。見上文。 |
stdout | "inherit" | "ignore" | 把子行程的 stdout 轉發到 Bun。預設 "ignore"。 |
stderr | "inherit" | "ignore" | 把子行程的 stderr 轉發到 Bun。預設 "ignore"。 |
例項屬性
| 屬性 | 型別 | 描述 |
|---|---|---|
url | string (readonly) | 當前 URL。導航完成後更新。首次導航前為空字串。 |
title | string (readonly) | 頁面 <title>。導航完成後更新。 |
loading | boolean (readonly) | 當正在進行導航時為 true。 |
onNavigated | ((url: string, title: string) => void) | null | 每次成功導航後觸發:在 navigate() promise 解析前觸發。 |
onNavigationFailed | ((error: Error) => void) | null | 每次失敗導航後觸發:在 navigate() promise 拒絕前觸發。 |
例項方法
| 方法 | 傳回值 | 描述 |
|---|---|---|
navigate(url) | Promise<void> | 載入 URL。在主框架的 load 事件觸發時解析。 |
evaluate(script) | Promise<unknown> | 在頁面中執行 JS 表示式,並傳回其經過 JSON 序列化的結果。 |
screenshot(options?) | Promise<Blob | Buffer | string | {name, size}> | 擷取視口。參見螢幕截圖。 |
click(x, y, options?) | Promise<void> | 在視口座標處執行原生點選。 |
click(selector, options?) | Promise<void> | 等待元素可操作,然後點選其中心。 |
type(text) | Promise<void> | 使用 InsertText 編輯命令將文本插入聚焦的元素。 |
press(key, options?) | Promise<void> | 按下命名的虛擬按鍵或單字元組合鍵。 |
scroll(dx, dy) | Promise<void> | 在視口中心觸發原生 wheel 事件。dx/dy 必須是有限值。 |
scrollTo(selector, options?) | Promise<void> | 等待元素存在,然後執行 scrollIntoView。 |
resize(width, height) | Promise<void> | 更改視口大小。每個維度的範圍為 1-16384。 |
goBack() | Promise<void> | 在會話歷史記錄中後退。在起始位置時不執行任何操作。 |
goForward() | Promise<void> | 在會話歷史記錄中前進。在末尾時不執行任何操作。 |
reload() | Promise<void> | 重新載入當前頁面。 |
cdp(method, params?) | Promise<unknown> | (僅限 Chrome)向此標籤頁傳送原始 CDP 命令。參見原始 CDP。 |
addEventListener(type, fn) | void | 繼承自 EventTarget。使用 Chrome 時,type 可以是 CDP 事件名稱;event.data 是經過解析的 params。 |
close() | void | 銷燬頁面。拒絕待處理的 promise。冪等。 |
click() 選項
| 選項 | 型別 | 預設值 | 描述 |
|---|---|---|---|
button | "left" | "right" | "middle" | "left" | 滑鼠按鍵。 |
modifiers | ("Shift" | "Control" | "Alt" | "Meta")[] | [] | 點選時按住的修飾鍵。 |
clickCount | 1 | 2 | 3 | 1 | 雙擊/三擊的點選次數。 |
timeout | number | 30000 | (僅選擇器過載)等待可操作性的最長毫秒數。 |
press() 選項
| 選項 | 型別 | 預設值 | 描述 |
|---|---|---|---|
modifiers | ("Shift" | "Control" | "Alt" | "Meta")[] | [] | 按下按鍵時按住的修飾鍵。 |
scrollTo() 選項
| 選項 | 型別 | 預設值 | 描述 |
|---|---|---|---|
block | "start" | "center" | "end" | "nearest" | "center" | 滾動後的垂直對齊方式。 |
timeout | number | 30000 | 等待元素存在的最長毫秒數。 |
screenshot() 選項
| 選項 | 型別 | 預設值 | 描述 |
|---|---|---|---|
format | "png" | "jpeg" | "webp" | "png" | 圖片格式。"webp" 需要 Chrome 後端。 |
quality | number | 80 | 0-100。僅 JPEG/WebP;PNG 會忽略。 |
encoding | "blob" | "buffer" | "base64" | "shmem" | "blob" | 傳回型別編碼。Windows 不支援 "shmem"。 |
靜態方法
| 方法 | 描述 |
|---|---|
WebView.closeAll() | SIGKILL 每個瀏覽器子行程。下一 tick 上拒絕所有待處理 promise。退出時自動呼叫。 |