wx.* API 支持状态
容器向页面注入全局 wx 对象。目前 60 个接口有真实行为,
18 个接口以空实现提供兼容。所有异步接口只支持回调风格,不返回 Promise。
success,失败回调是 fail,
结束回调是 complete。回调在宿主主线程执行,可直接调用 setData。
网络
| 接口 | 参数 | 回调 |
|---|---|---|
wx.request | url、method(GET/HEAD/POST/PUT/DELETE/PATCH)、data、header、timeout(毫秒,默认 60000)、responseType(text / arraybuffer) | success({ data, statusCode, header, cookies }) / fail({ errMsg, statusCode, data, header }) / complete() |
wx.getNetworkType | — | success({ networkType }),值为 wifi / ethernet / none |
wx.onNetworkStatusChange | callback({ isConnected, networkType }) | 网络类型变化时触发(约 2 秒轮询一次);wx.offNetworkStatusChange 取消 |
GET / HEAD 会把 data 序列化为查询串,其他方法发送请求体;
未显式设置时自动补 Content-Type: application/json,data
为字符串时原样发送。responseType: "arraybuffer" 时 data
是 ArrayBuffer,可配合 Uint8Array 处理下载的二进制内容。
success 回调的 cookies 字段汇总了整条重定向链上的
Set-Cookie(键为 cookie 名),可用于登录态透传。
回调语义与微信一致:只要服务端返回了 HTTP 响应(包括
401 / 404 / 500),都会走 success,
由脚本按 statusCode 自行判断;fail 只在网络层失败时触发
(DNS、连接被拒、超时、TLS 等),且同样带上 statusCode、
data、header,errMsg 形如
"request:fail timeout"。
url 以 / 开头时按商店服务端地址解析,便于首页这类
“由服务端下发、内容随服务端更新”的小程序直接请求 /api/v1/miniapp-home。
wx.request({
url: 'https://example.com/api/list',
method: 'POST',
data: { page: 1 },
success(res) {
this.setData({ items: res.data.items });
}
});
数据源(SMB)
容器内置 libsmb2,通过 wx.smb.* 访问局域网 SMB 共享
(Windows 共享、群晖、飞牛、极空间等)。连接与列目录为阻塞操作,在
工作线程执行;success / fail 回调在宿主主线程触发。
会话 id 随容器进程存活,不持久化到磁盘。
| 接口 | 参数 | 说明 |
|---|---|---|
wx.smb.connect | server、share、user、password、domain(可选) | 连接共享,success({ id }) 返回会话 id;fail({ errMsg }) |
wx.smb.listFiles | id、path | 列目录,success([{ name, isDir, size }]);name 为共享内完整路径(/ 分隔) |
wx.smb.streamUrl | id、path | 返回本地 HTTP 代理播放地址(同步),可直接赋给 <video src>;代理端口全部占用时返回空串,应先判断再使用 |
wx.smb.scan | id、path、maxDepth(可选,默认 4)、maxEntries(可选)、progress({ dirs, files })(可选) | 在宿主线程递归遍历目录树,一次回调返回全部文件条目 [{ name, isDir, size }],比逐目录 listFiles 快很多;扫描中回调进度,配合 wx.smb.cancelScan() 可中途取消 |
wx.smb.cancelScan | — | 取消正在进行的 scan,已收集的文件仍会通过 success 返回 |
wx.smb.disconnect | id | 断开会话并释放资源 |
wx.smb.connect({
server: '192.168.1.100',
share: 'movies',
user: 'admin',
password: 'xxx',
success(res) {
var smbId = res.id;
// 递归扫描视频文件:path 传目录,name 为完整路径
wx.smb.listFiles({
id: smbId,
path: '/',
success(files) {
this.setData({ files: files.filter(function (f) { return !f.isDir; }) });
}
});
},
fail(err) {
console.error(err.errMsg);
}
});
// 播放:拿本地代理地址后交给 video(或 setData 到 src)
var url = wx.smb.streamUrl({ id: smbId, path: '/movies/a.mp4' });
播放走容器本地 HTTP 代理(127.0.0.1),支持 Range
请求(返回 206 Partial Content),由 MPV 直接拉取局域网数据流,
无需把整段视频读入内存。单次代理读取上限 4MB,MPV 会按 Range 分块请求。
媒体库索引(wx.media)
把“遍历目录 + 索引”下沉到宿主:索引按数据源落盘,目录修改时间未变化时 直接复用旧结果,后续进入只读本地索引,毫秒级返回。适用于影片数量多、 每次进入都要重扫的场景(如 SMB 影视库)。
| 接口 | 参数 | 说明 |
|---|---|---|
wx.media.scan | sourceId、id(SMB 会话 id)、root、maxDepth(可选,默认 4)、maxFiles(可选,默认 2000) | 增量扫描并写盘索引,只收录视频文件;success({ total }) 返回索引内文件总数 |
wx.media.library | sourceId、root、offset(可选)、limit(可选,0 表示全部) | 读取索引,success({ total, list: [{ name, size, subtitle? }] });name 为共享内完整路径,subtitle 为同目录同名外挂字幕(.srt/.ass/.ssa/.vtt)的完整路径。索引与扫描根绑定:root 与建索引时不一致会返回空(等重新扫描),避免换了子目录后仍展示旧目录内容 |
// 先读库(有索引时立即返回),无索引或需要刷新时再触发增量扫描
wx.media.library({
sourceId: source.id, root: '/',
success(page) {
if (page.list.length) render(page.list);
else wx.media.scan({
sourceId: source.id, id: smbId, root: '/',
success(res) { console.log('indexed', res.total); }
});
}
});
界面交互
| 接口 | 参数 | 说明 |
|---|---|---|
wx.showToast | title、icon、duration | 绘制在屏幕底部,默认 2000ms |
wx.showLoading | title | 全屏遮罩,需要手动关闭 |
wx.hideLoading | — | 关闭 loading |
wx.showModal | title、content、showCancel、confirmText、cancelText | 宿主弹窗;success({ confirm, cancel }) |
wx.setNavigationBarTitle | title | 更新页面标题 |
wx.nextTick | callback | 下一帧执行 |
wx.vibrateShort | type(heavy / medium / light) | Switch 上复用 borealis 输入层的震动设备(HD 震动,约 180ms 后由主线程清零);不支持震动的设备静默降级 |
wx.canIUse | schema | 按当前已注入能力返回布尔值 |
游戏能力
| 接口 | 参数 | 说明 |
|---|---|---|
wx.getGamepadState() | — | 同步返回 { connected, axes: [LX, LY, RX, RY], buttons: { a, b, x, y, lb, rb, lt, rt, up, down, left, right, start, back, lsb, rsb }, pressed: [...] };摇杆取值 -1..1,适合在 requestAnimationFrame 循环里逐帧读取 |
requestAnimationFrame(fn) | fn(timestamp) | 每帧回调一次(容器 tick 驱动),返回可用于 cancelAnimationFrame 的 id;回调里需要再次注册才会持续触发 |
cancelAnimationFrame(id) | id | 取消尚未执行的帧回调 |
wx.connectSocket({ url }) | url 支持 ws:// 与 wss:// | 返回 SocketTask:onOpen(cb) / onMessage(cb) / onError(cb) / onClose(cb) / send({ data }) / close()。网络线程收包,回调在主线程按帧派发 |
// 手柄驱动的方块 + 联机回显
const socket = wx.connectSocket({ url: 'wss://echo.websocket.events' });
socket.onMessage(res => console.log('recv', res.data));
function loop(ts) {
const pad = wx.getGamepadState();
player.x += pad.axes[0] * 4;
if (pad.buttons.a) jump();
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
Switch 硬件(wx.nx)
wx.nx 只在本机型容器上有意义:桌面构建返回
{ supported: false },用于页面布局预览。红外、NFC 都依赖右 Joy-Con,
红外相机需要把右 Joy-Con 从本体上拆下来才能取到画面(插在本体上镜头被遮挡)。
| 接口 | 参数 | 说明 |
|---|---|---|
wx.nx.motion.state() | — | 同步返回六轴快照:{ supported, connected, count, gyro: [x,y,z] (rad/s), accel: [x,y,z] (g), angle: [roll,pitch,yaw] (rad), controllers: [...] }。适合在 requestAnimationFrame 或 setInterval 里轮询 |
wx.nx.rumble.play({ lowFreq, highFreq, lowAmp, highAmp, duration }) | 频率 Hz(40~1250),振幅 0..1,时长 ms(0 表示持续) | 直接写 HD 震动设备的频率/振幅,可自行拼出波形;配合 setTimeout 可播摩尔斯电码 |
wx.nx.rumble.stop() | — | 立即停止震动 |
wx.nx.ir.start(mode) | image / gesture | image:红外画面(320×240);gesture:红外聚类,返回手部/物体包围盒与像素密度。两种模式互斥 |
wx.nx.ir.stop() | — | 停止红外处理并关闭服务 |
wx.nx.ir.state() | — | { supported, running, mode, width, height, frameVersion, ambientNoise, blobs, hand };hand 为最大聚类块 { x, y, width, height, pixels, density, centroidX, centroidY },可用密度与像素数区分张手/握拳 |
ctx.drawIrCamera(x, y, w, h) | — | 画布方法:把最新红外帧画进当前 ctx,帧率约 30fps;调用后再 ctx.draw() |
wx.nx.nfc.start() | — | 启动 Amiibo/NFC 检测(nfp:user),结果通过 state() 轮询 |
wx.nx.nfc.state() | — | { supported, running, state: idle|searching|found|mounted|unavailable|error, uid, tagType, protocol, mounted, amiibo } |
wx.nx.nfc.mount() | — | 挂载当前卡片并读取 Amiibo 信息与应用存档区。amiibo 含 name、characterId、seriesId、numberingId、appAreaSize、appArea(hex)等字段 |
wx.nx.nfc.unmount() | — | 卸载当前卡片,继续检测下一张 |
wx.nx.nfc.writeAppArea(hex) | hex 字符串 | 把备份数据写回已挂载 Amiibo 的应用存档区并 nfpFlush;只写存档区,不改写角色/UID 等身份数据。写入前请确认卡片可写 |
wx.nx.nfc.stop() | — | 停止检测并退出 NFC 服务 |
// 体感 + 红外画面
function loop() {
const m = wx.nx.motion.state();
tilt = m.angle[0];
const ir = wx.nx.ir.state();
if (ir.running && ir.mode === 'image') {
ctx.drawIrCamera(0, 0, 320, 240);
ctx.draw();
}
requestAnimationFrame(loop);
}
wx.nx.ir.start('image');
requestAnimationFrame(loop);
// 红外手势:根据最大聚类块的密度做张手/握拳判定
wx.nx.ir.start('gesture');
setInterval(() => {
const hand = wx.nx.ir.state().hand;
if (hand && hand.pixels > 900) {
console.log(hand.density > 0.62 ? '握拳' : '张开');
}
}, 100);
// NFC:发现卡片后挂载读取
wx.nx.nfc.start();
setInterval(() => {
const nfc = wx.nx.nfc.state();
if (nfc.state === 'found') wx.nx.nfc.mount();
if (nfc.state === 'mounted') console.log(nfc.amiibo.name, nfc.amiibo.appAreaSize);
}, 200);
// 自定义 HD 震动波形
wx.nx.rumble.play({ lowFreq: 90, highFreq: 90, lowAmp: 1, highAmp: 0.2, duration: 700 });
画布
| 接口 | 参数 | 说明 |
|---|---|---|
wx.createCanvasContext(id) | id 对应 <canvas id="..."> | 返回 2D 上下文,支持 setFillStyle / setStrokeStyle / setLineWidth / setFontSize / setTextAlign / setGlobalAlpha |
绘制 API:fillRect、strokeRect、clearRect、
beginPath、closePath、moveTo、lineTo、
rect、arc、fill、stroke、
fillText、drawImage、drawIrCamera、save、restore、
translate、scale、rotate。
所有指令缓存在 JS 侧,调用 ctx.draw() 后才提交为当前帧,
由 NanoVG 按 node.absWidth / canvasWidth 缩放回放。
const ctx = wx.createCanvasContext('game');
ctx.setFillStyle('#10dc78');
ctx.fillRect(x, y, 32, 32);
ctx.draw();
媒体
| 接口 | 参数 | 说明 |
|---|---|---|
wx.createVideoContext(id) | id 对应 <video id="..."> | 返回控制器:play() / pause() / stop() / seek(seconds) / requestFullScreen() / exitFullScreen() / setPlaybackRate(rate) / setVolume(0-100) / addSubtitle(url) |
wx.createInnerAudioContext() | — | 返回音频实例:属性 src、autoplay、loop、volume(0-1)、startTime、只读 duration / currentTime / paused;方法 play() / pause() / stop() / seek(t) / destroy();事件 onPlay / onPause / onStop / onEnded / onCanplay / onError / onSeeked |
const ctx = wx.createVideoContext('demoVideo');
ctx.play();
ctx.seek(30);
ctx.setPlaybackRate(1.5);
ctx.setVolume(60);
ctx.requestFullScreen();
ctx.addSubtitle('https://example.com/movie.zh.srt');
// 音频:所有实例共用一路纯音频播放器(Switch 的音频渲染器是进程级单例,
// 多路 mpv 同时出声会崩)。同一时刻只播一个音源;音效播完后会自动恢复
// 被打断的循环音轨,并回到原来的播放位置。
const bgm = wx.createInnerAudioContext();
bgm.src = '/assets/bgm.wav';
bgm.loop = true;
bgm.volume = 0.4;
bgm.play();
const beep = wx.createInnerAudioContext();
beep.src = '/assets/beep.wav';
beep.play(); // 打断 BGM;结束(onEnded)后 BGM 自动接着放
beep.destroy(); // 页面卸载时释放
<video> 支持的扩展属性:initial-time(起播秒数)、
playback-rate(倍速,1 为正常)、volume(0-100)、
subtitle(外挂字幕地址,支持 smb://会话id/路径 或
sdmc:/... 本地路径)、http-headers(鉴权直链的 Cookie)、
autoplay、loop、muted、poster、
object-fit。
事件:bindplay、bindpause、bindended、
bindtimeupdate、binderror、bindloadedmetadata、
bindwaiting、bindprogress、bindseekcomplete、
bindfullscreenchange。全屏时画面铺满内容区,按 B 退出并派发
bindfullscreenchange({ fullScreen })。
实际解码由 nxkit::MPVCore 完成。桌面构建默认关闭
NXKIT_WITH_MPV,需要安装 libmpv 并重新配置;未启用时
video 只显示 poster 与占位控制条,并派发 binderror。
小程序互跳
| 接口 | 参数 | 说明 |
|---|---|---|
wx.miniapp.launch(id) | 小程序 ID,或 { id } | 已安装则直接进入;未安装会先下载安装。返回布尔值表示是否已受理 |
wx.miniapp.listRecent() | — | 返回最近使用的数组:[{ id, title, count, installed }],按最近使用倒序 |
wx.miniapp.deviceId() | — | 返回容器持久化的设备标识(首次生成后写入配置),用于服务端 UV 统计上报 |
const recent = wx.miniapp.listRecent();
wx.miniapp.launch(recent[0].id);
首页小程序就是靠这两个接口组织“推荐 / 最近使用”的;客户端启动时会先请求
/api/v1/miniapp-home 拿到首页小程序,再按版本安装运行。
数据缓存
| 接口 | 说明 |
|---|---|
wx.setStorageSync(key, data) | 写入并同步落盘,值为 JSON 字符串 |
wx.getStorageSync(key) | 读取并反序列化,不存在返回 "" |
wx.removeStorageSync(key) | 删除单个键 |
wx.clearStorageSync() | 清空当前小程序缓存 |
wx.setStorage / getStorage / removeStorage / clearStorage | 回调风格的异步版本 |
wx.getStorageInfoSync() | { keys, currentSize, limitSize } |
wx.getStorageInfo() | 异步返回同样的结构 |
缓存按小程序包隔离,保存在 miniapp/storage/<hash>.json。
路由
| 接口 | 参数 | 行为 |
|---|---|---|
wx.navigateTo | url 可带 query | 压栈并触发 onHide / onLoad / onShow |
wx.navigateBack | delta | 出栈并触发 onUnload |
wx.redirectTo | url | 替换当前页 |
wx.reLaunch | url | 清空页面栈后打开目标页 |
wx.navigateTo({ url: '/pages/detail/detail?id=42' });
// detail.js
Page({
onLoad(query) {
this.setData({ id: query.id });
}
});
系统信息与启动参数
| 接口 | 说明 |
|---|---|
wx.getSystemInfoSync() | 返回 windowWidth、windowHeight、platform、SDKVersion 等 |
wx.getSystemInfo() | 回调风格的异步版本 |
keyEvents | getSystemInfoSync() 字段,为 true 时支持页面 onKeyDown 按键事件 |
wx.getWindowInfo() | 窗口尺寸与安全区 |
wx.getDeviceInfo() | 设备型号、系统、平台 |
wx.getAppBaseInfo() | 语言、版本、主题、SDKVersion |
wx.getMenuButtonBoundingClientRect() | 无胶囊按钮,返回零尺寸矩形 |
wx.getLaunchOptionsSync() | { path, query, scene } |
wx.getEnterOptionsSync() | 同启动参数 |
剪贴板与更新
| 接口 | 说明 |
|---|---|
wx.setClipboardData({ data }) | 写入进程内剪贴板 |
wx.getClipboardData() | success({ data }) |
wx.getUpdateManager() | 返回带 onCheckForUpdate / onUpdateReady / applyUpdate 的空实现对象 |
兼容占位接口
以下接口存在但不会产生效果,用于让微信代码平滑运行:
setNavigationBarColor、showNavigationBarLoading、
hideNavigationBarLoading、setKeepScreenOn、
setPreferredFramesPerSecond、reportAnalytics、
reportEvent、onNetworkStatusChange、
onAppShow、onAppHide、onError、
onUnhandledRejection、pageScrollTo 及对应的
off* 接口。
全局对象
| 名称 | 说明 |
|---|---|
Page(options) | 注册页面,data 与生命周期、方法;可选 onKeyDown 接收手柄按键 |
App(options) | 注册应用级对象,支持 onLaunch / onShow / onHide |
getApp() | 返回 App 实例 |
getCurrentPages() | 返回页面路径数组 |
setTimeout / setInterval / clearTimeout / clearInterval | 由容器每帧驱动 |
console.log / info / warn / error | 写入宿主日志 |
wx.* 均为未实现;调用会得到 undefined。