Skip to content

脚本 API 附录

目标

说明站点页面脚本和接口拦截脚本可以使用的 window.api 能力,包括配置读取、HTTP 请求、用户数据、DOM 工具、通用工具、请求头和响应头读取。

页面脚本和普通接口拦截脚本可以使用 window.api。SSE 脚本只保证传入 data,通常不依赖 window.api

ts
interface Window {
  api: {
    user: UserApi;
    http: HttpApi;
    config: Record<string, unknown>;
    dom: DomApi;
    utils: UtilsApi;
    header(headerName: string, isRequestHeader: boolean): Promise<string | string[] | undefined>;
  };
}

api.config

读取站点脚本环境中的自定义配置。

ts
config: Record<string, unknown>

示例:

js
const apiBase = api.config.apiBase;

api.http

api.http 为用户脚本提供 HTTP 请求工具。api.http.ajax 会在浏览器主进程中执行实际请求,因此不受页面 CORS 策略限制。

api.http.ajax(options)

发送 HTTP 请求。

ts
ajax(options: {
  url: string;
  method?: string;
  data?: any;
  headers?: Record<string, string>;
  timeout?: number;
  dataType?: 'json' | 'text' | 'html' | 'arrayBuffer';
  contentType?: string;
  processData?: boolean;
}): Promise<{
  ok: boolean;
  status: number;
  statusText: string;
  data?: any;
  error?: string;
  timeout?: boolean;
}>
选项类型默认值说明
urlstring-请求 URL。
methodstringGETHTTP 方法。
dataany-请求数据。GETHEAD 请求会序列化到查询字符串;其它方法会写入请求体。
headersRecord<string, string>{}请求头。
timeoutnumber-超时时间,单位毫秒。仅大于 0 时生效。
dataType'json' | 'text' | 'html' | 'arrayBuffer'json响应解析方式。
contentTypestringapplication/x-www-form-urlencoded; charset=UTF-8请求体 Content-Type。
processDatabooleantrue是否自动序列化 data。设为 false 时会把 data 直接作为请求体传入。

返回值:

字段类型说明
okbooleanHTTP 2xx 响应为 true;解析错误、HTTP 错误、超时、中止或网络错误为 false
statusnumberHTTP 状态码。0 表示超时、中止或网络层失败。
statusTextstringHTTP 状态文本;非 HTTP 失败时为 timeoutaborterror
dataany解析成功后的响应数据。
errorstring解析失败或非 HTTP 失败时的错误消息。
timeoutboolean请求因配置的超时时间被中止时为 true

示例:

js
const ret = await api.http.ajax({
  url: 'https://example.com/api/profile',
  method: 'GET',
  dataType: 'json',
  timeout: 10000
});

if (ret.ok) {
  console.log(ret.data);
}
js
const ret = await api.http.ajax({
  url: 'https://example.com/api/items',
  method: 'POST',
  contentType: 'application/json',
  data: { name: 'demo' }
});

api.user

api.user 用于读写脚本运行过程中的用户关联数据。

通用参数:

参数类型默认值说明
sitebooleanfalse是否分站点存储。
accountbooleanfalse是否分账号存储。
didbooleanfalse是否分设备存储。

api.user.put(name, value, site, account, did)

保存指定键值。

ts
put(
  name: string,
  value: string,
  site?: boolean,
  account?: boolean,
  did?: boolean
): Promise<{ status: boolean }>

示例:

js
await api.user.put('token', 'abc123');

api.user.get(name, site, account, did)

读取指定键值。

ts
get(
  name: string,
  site?: boolean,
  account?: boolean,
  did?: boolean
): Promise<{ value: string | null, status: boolean }>

示例:

js
const ret = await api.user.get('token');
console.log(ret.value);

api.user.remove(name, site, account, did)

删除指定键值。

ts
remove(
  name: string,
  site?: boolean,
  account?: boolean,
  did?: boolean
): Promise<{ status: boolean }>

示例:

js
await api.user.remove('token');

api.user.incr(name, step, site, account, did)

按步长增加指定键的数值。键不存在时会创建该键,值为 step

ts
incr(
  name: string,
  step?: number,
  site?: boolean,
  account?: boolean,
  did?: boolean
): Promise<{ status: boolean, value: number | string }>

示例:

js
const ret = await api.user.incr('count', 1);
console.log(ret.value);

api.user.decr(name, step, site, account, did)

按步长减少指定键的数值。键不存在时会创建该键,值为 step * -1

ts
decr(
  name: string,
  step?: number,
  site?: boolean,
  account?: boolean,
  did?: boolean
): Promise<{ status: boolean, value: number | string }>

示例:

js
const ret = await api.user.decr('count', 1);
console.log(ret.value);

api.user.startsWith(prefix, site, account, did)

查找所有键名以指定前缀开头的数据。

ts
startsWith(
  prefix: string,
  site?: boolean,
  account?: boolean,
  did?: boolean
): Promise<Array<{ name: string, value: string }>>

示例:

js
const items = await api.user.startsWith('cache:');

api.user.countAll(name, site, account)

统计指定键名的记录数量。

ts
countAll(
  name: string,
  site?: boolean,
  account?: boolean
): Promise<{ value: number, status: boolean }>

示例:

js
const ret = await api.user.countAll('token');
console.log(ret.value);

api.user.sumAll(name, site, account)

统计指定键名对应值的数值总和。

ts
sumAll(
  name: string,
  site?: boolean,
  account?: boolean
): Promise<{ value: number, status: boolean }>

示例:

js
const ret = await api.user.sumAll('score');
console.log(ret.value);

api.dom

api.dom 提供 DOM 查询、可见性判断、连接监听、尺寸监听和覆盖层创建能力。

选择器支持:

写法说明
.button.primaryCSS 选择器。
xpath://div[@id="app"]XPath 选择器。
.dialog:p返回匹配元素的父元素。
.dialog:p2返回匹配元素向上两级的父元素。
.header:bottom覆盖层边界方法中取目标元素下边界。
.sidebar:right覆盖层边界方法中取目标元素右边界。

api.dom.createMutationObserver(ele, bindStr, childList, subtree, attributes, characterData, fn)

创建并缓存 MutationObserver。如果 ele[bindStr] 已存在,会直接返回已有 observer。

ts
createMutationObserver(
  ele: Element,
  bindStr: string,
  childList: boolean,
  subtree: boolean,
  attributes: boolean,
  characterData: boolean,
  fn: (mutations: MutationRecord[]) => void
): MutationObserver

示例:

js
api.dom.createMutationObserver(
  document.body,
  '__bodyObserver__',
  true,
  true,
  false,
  false,
  (mutations) => console.log(mutations)
);

api.dom.querySelector(doc, cssOrXPathSelector)

查询第一个匹配元素。

ts
querySelector(doc: Document, cssOrXPathSelector: string): HTMLElement | null

示例:

js
const el = api.dom.querySelector(document, 'xpath://button[contains(.,"提交")]');

api.dom.querySelectorAll(doc, cssOrXPathSelector)

查询所有匹配元素。

ts
querySelectorAll(doc: Document, cssOrXPathSelector: string): HTMLElement[]

示例:

js
const buttons = api.dom.querySelectorAll(document, 'button.primary');

api.dom.isVisible(ele)

判断元素是否处于可见交叉区域。

ts
isVisible(ele: HTMLElement): Promise<boolean>

示例:

js
if (await api.dom.isVisible(el)) {
  console.log('visible');
}

api.dom.getVisibleRect(ele)

获取元素当前可见区域矩形。

ts
getVisibleRect(ele: HTMLElement): Promise<DOMRectReadOnly>

示例:

js
const rect = await api.dom.getVisibleRect(el);
console.log(rect.left, rect.top, rect.width, rect.height);

api.dom.getConnectListeners()

获取当前连接监听器列表。

ts
getConnectListeners(): Array<{
  querySelector: string;
  callback: (isConnected: boolean) => void;
  isConnected?: boolean;
}>

示例:

js
api.dom.addConnectListener('.modal', () => {});
console.log(api.dom.getConnectListeners());

api.dom.addConnectListener(cssOrXPathSelector, callback)

监听目标元素是否出现在文档中或从文档中消失。

ts
addConnectListener(
  cssOrXPathSelector: string,
  callback: (isConnected: boolean) => void
): void

示例:

js
api.dom.addConnectListener('.dialog', (isConnected) => {
  console.log('dialog:', isConnected);
});

api.dom.removeConnectListener(cssOrXPathSelectors)

移除指定选择器对应的连接监听器。

ts
removeConnectListener(cssOrXPathSelectors: string[]): void

示例:

js
api.dom.removeConnectListener(['.dialog', '.toast']);

api.dom.addResizeListener(cssOrXPathSelector, bindWindowStr, callback, createObserver, delayTime)

监听目标元素尺寸和位置变化。元素不存在时,回调会收到 new DOMRect(0, 0, 0, 0)

ts
addResizeListener(
  cssOrXPathSelector: string,
  bindWindowStr: string,
  callback: (rect: DOMRect) => void,
  createObserver?: boolean,
  delayTime?: number
): ResizeObserver | (() => void)

示例:

js
api.dom.addResizeListener('.target', '__targetResize__', (rect) => {
  console.log(rect.width, rect.height);
});

api.dom.createOverlayBy(cssOrXPathSelector, bindWindowStr, createObserver, delayTime, fn)

创建一个跟随目标元素可见区域的固定定位覆盖层。

ts
createOverlayBy(
  cssOrXPathSelector: string,
  bindWindowStr: string,
  createObserver?: boolean,
  delayTime?: number,
  fn?: (rect: DOMRectReadOnly) => void
): HTMLElement

示例:

js
const overlay = api.dom.createOverlayBy('.target', '__overlay__');
overlay.style.border = '2px solid #f00';
overlay.style.pointerEvents = 'none';
overlay.style.zIndex = '999999';

api.dom.createOverlayByBorder(bindWindowStr, top, right, bottom, left, createObserver, delayTime)

通过四条边创建固定定位覆盖层。每条边可以是数字像素值,也可以是选择器。选择器边界可配合 :top:right:bottom:left 指定使用哪条边。

ts
createOverlayByBorder(
  bindWindowStr: string,
  top: string | number,
  right: string | number,
  bottom: string | number,
  left: string | number,
  createObserver?: boolean,
  delayTime?: number
): HTMLElement

示例:

js
const panel = api.dom.createOverlayByBorder(
  '__centerPanel__',
  'header:bottom',
  20,
  'footer:top',
  '.sidebar:right'
);
panel.style.background = 'rgba(0,0,0,.08)';

api.utils

api.utils.wait(fn, timeoutMs, intervalMs)

轮询等待条件函数返回真值。

ts
wait(
  fn: () => boolean,
  timeoutMs: number,
  intervalMs?: number
): Promise<void>

超时后会抛出 Error("Timeout: function did not return true in time.")

示例:

js
await api.utils.wait(
  () => !!api.dom.querySelector(document, '.ready'),
  10000,
  200
);

api.utils.runScript(code, callback)

在当前页面执行 JavaScript 代码。

ts
runScript(
  code: string,
  callback?: (result: any, error: Error) => void
): Promise<any>

示例:

js
const title = await api.utils.runScript('document.title');
console.log(title);

api.header(headerName, isRequestHeader)

读取远程浏览器记录的请求头或响应头。

ts
header(
  headerName: string,
  isRequestHeader: boolean
): Promise<string | string[] | undefined>
参数类型说明
headerNamestring请求头或响应头名称,读取时会转成小写。
isRequestHeaderbooleantrue 读取请求头,false 读取响应头。

注意:

  • 只有在站点配置中添加过的请求头或响应头才会被记录。
  • 请求头来自远程浏览器发送请求时的 header。
  • 响应头来自远程浏览器收到响应时的 header。
  • 响应头可能返回字符串数组。

示例:

js
const cookie = await api.header('cookie', true);
const setCookie = await api.header('set-cookie', false);

Sa2web 1.0.0