XuqmGroup-RNSDK/docs/XWebView-JSBridge.md

212 行
5.9 KiB
Markdown

# XWebView JSBridge 标准接口
> 最后更新2026-06-15
---
## 概述
XWebView 内置 JSBridge,支持 H5 页面与 React Native 宿主之间的双向通信。
**通信机制**
- H5 → RN`window.ReactNativeWebView.postMessage(JSON.stringify(data))`
- RN → H5`webViewRef.injectJavaScript(jsString)`
---
## 一、H5 → RN 消息协议
### 1.1 内置消息__xwv 前缀)
XWebView 自动拦截以下浏览器行为,通过 `postMessage` 发送给 RN
| 消息类型 | 触发场景 | 数据格式 |
|---------|---------|---------|
| `alert` | `window.alert(msg)` | `{__xwv: 'alert', msg: string}` |
| `confirm` | `window.confirm(msg)` | `{__xwv: 'confirm', msg: string}` |
| `prompt` | `window.prompt(msg, def)` | `{__xwv: 'prompt', msg: string, def: string}` |
| `download` | 点击下载链接 | `{__xwv: 'download', url: string, filename: string}` |
| `blobdownload` | blob URL 下载 | `{__xwv: 'blobdownload', url: string, filename: string, data: base64}` |
| `bloberror` | blob 读取失败 | `{__xwv: 'bloberror', msg: string}` |
| `log` | 调试日志 | `{__xwv: 'log', msg: string}` |
### 1.2 自定义消息
H5 发送非 `__xwv` 前缀的消息时,XWebView 将其转发给 `onMessage` 回调:
```javascript
// H5 端
window.ReactNativeWebView.postMessage(JSON.stringify({
type: 'customEvent',
payload: { key: 'value' }
}));
```
```typescript
// RN 端
<XWebViewView
onMessage={(event) => {
const data = JSON.parse(event.nativeEvent.data);
if (data.type === 'customEvent') {
// 处理自定义消息
}
}}
/>
```
---
## 二、RN → H5 通信
### 2.1 注入 JavaScript
```typescript
// 通过 controller API
controller.postMessageToWeb('window.dispatchEvent(new CustomEvent("rnMessage", {detail: {type: "update", data: "hello"}}))');
// 通过 ref
webViewRef.injectJavaScript('window.handleRNMessage("hello")');
```
### 2.2 Controller API
通过 `setXWebViewController` 获取的 controller 对象提供以下方法:
| 方法 | 说明 |
|------|------|
| `refresh()` | 刷新当前页面 |
| `close()` | 关闭 WebView |
| `goBack()` | 返回上一页 |
| `goForward()` | 前进 |
| `copyUrl()` | 复制当前 URL 到剪贴板 |
| `postMessageToWeb(jsString)` | 向 H5 注入并执行 JS |
| `getTitle()` | 获取当前页面标题 |
---
## 三、下载处理
### 3.1 自动下载拦截
XWebView 自动拦截以下文件扩展名的链接点击:
```
.pdf .zip .rar .tar .gz .apk .ipa .doc .docx .xls .xlsx .ppt .pptx .mp4 .mp3 .mov .exe .dmg
```
### 3.2 下载回调
```typescript
<XWebViewView
autoDownload={true}
onDownloadStart={(request) => {
// request: { url, suggestedFilename, mimeType?, fileSize? }
console.log('Download started:', request.suggestedFilename);
}}
onDownloadProgress={(progress) => {
// progress: { url, filename, received, total, percentage }
console.log(`Download: ${progress.percentage}%`);
}}
onDownloadComplete={(result) => {
// result: { url, filename, filePath, fileSize }
console.log('Download complete:', result.filePath);
}}
onDownloadError={(url, error) => {
console.error('Download failed:', url, error);
}}
onDownloadDecide={(request) => {
// 返回下载决策
return { allowed: true, filename: request.suggestedFilename };
}}
downloadConflict="rename" // 'rename' | 'overwrite'
/>
```
### 3.3 Blob URL 下载
XWebView 自动处理 blob URL 下载:
1. 拦截 `<a href="blob:...">` 点击
2. 通过 `FileReader` 读取 blob 数据为 base64
3. 通过 `saveBase64File` 保存到本地
---
## 四、内置 Dialog 覆盖
XWebView 注入 `DIALOG_OVERRIDE_JS`,覆盖浏览器原生对话框:
| 原生方法 | 覆盖行为 |
|---------|---------|
| `window.alert(msg)` | 发送 `{__xwv: 'alert', msg}` 消息 |
| `window.confirm(msg)` | 发送 `{__xwv: 'confirm', msg}` 消息,始终返回 `true` |
| `window.prompt(msg, def)` | 发送 `{__xwv: 'prompt', msg, def}` 消息,返回默认值 |
| `window.open(url)` | 发送日志消息,然后 `window.location.href = url` |
RN 端收到这些消息后,可以展示原生 Alert/Confirm/Prompt 对话框。
---
## 五、标准 Bridge 接口(宿主实现)
以下接口由宿主应用通过 `bridgeHandlers` 实现,H5 通过 `xuqm.call(method, params)` 调用:
### 5.1 会话管理
| 接口 | 参数 | 返回值 | 说明 |
|------|------|--------|------|
| `getSession` | — | `{token, userId}` | 获取当前登录会话 |
| `getUserInfo` | — | `{userId, name, phone, avatar}` | 获取用户信息 |
### 5.2 导航
| 接口 | 参数 | 返回值 | 说明 |
|------|------|--------|------|
| `navigate` | `{screen, params?}` | — | 跳转宿主页面 |
| `close` | — | — | 关闭当前 WebView |
| `goBack` | — | — | 返回上一页 |
### 5.2 UI 交互
| 接口 | 参数 | 返回值 | 说明 |
|------|------|--------|------|
| `showToast` | `{message}` | — | 显示 Toast |
| `showAlert` | `{title?, message}` | — | 显示 Alert 对话框 |
| `showConfirm` | `{title?, message, confirmText?, cancelText?}` | `{confirmed: boolean}` | 显示确认对话框 |
### 5.3 文件操作
| 接口 | 参数 | 返回值 | 说明 |
|------|------|--------|------|
| `uploadFile` | `{accept?}` | `{url, name, size}` | 选择并上传文件 |
| `openCamera` | — | `{url, base64}` | 打开相机拍照 |
| `scanQR` | — | `{result}` | 扫描二维码 |
### 5.4 设备信息
| 接口 | 参数 | 返回值 | 说明 |
|------|------|--------|------|
| `getDeviceInfo` | — | `{platform, version, model}` | 获取设备信息 |
| `getLocation` | — | `{latitude, longitude}` | 获取当前位置 |
---
## 六、H5 端调用示例
```javascript
// 获取会话
xuqm.call('getSession').then(session => {
console.log('Token:', session.token);
});
// 跳转宿主页面
xuqm.call('navigate', { screen: 'Settings' });
// 显示 Toast
xuqm.call('showToast', { message: '操作成功' });
// 上传文件
xuqm.call('uploadFile', { accept: 'image/*' }).then(file => {
console.log('Uploaded:', file.url);
});
```