XuqmGroup-Web/docs-site/docs/rn/xwebview.md
2026-07-29 02:43:17 +08:00

250 行
5.4 KiB
Markdown

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

# XWebView
`@xuqm/rn-xwebview` 提供可直接打开的独立 WebView 页面,也支持在业务页面中嵌入浏览器
内核。SDK 只提供通用容器和 Bridge 接入入口,不内置任何宿主业务协议。
## 安装
```bash
pnpm add @xuqm/rn-common @xuqm/rn-xwebview \
react-native-webview react-native-svg \
@react-native-clipboard/clipboard react-native-safe-area-context
```
这些原生依赖需要由宿主直接声明,以便 React Native 自动链接。
## 根部挂载 Host
独立页面模式需要在应用根部挂载一次:
```tsx
import { XWebViewHost } from '@xuqm/rn-xwebview'
export function App() {
return (
<>
<RootNavigation />
<XWebViewHost />
</>
)
}
```
全局只能存在一个 `XWebViewHost`
## 打开独立页面
```ts
import { openWebView } from '@xuqm/rn-xwebview'
const page = openWebView({
source: {
uri: 'https://example.com',
headers: {
'X-From-App': 'true',
},
},
navigationBar: {
title: {
text: '服务页面',
mode: 'web',
},
},
statusBar: {
translucent: true,
contentStyle: 'dark-content',
},
})
const result = await page.closed
console.log(result.reason, result.data)
```
返回的页面 Handle 可以:
```ts
page.reload()
page.goBack()
page.goForward()
page.postMessage(JSON.stringify({ type: 'refresh' }))
page.evaluateJavaScript('window.refreshPage?.()')
page.suspend()
page.resume()
page.close('api', { completed: true })
```
`suspend()` 用于临时展示宿主原生页面,页面实例和网页历史会保留;完成后调用
`resume()`
## 默认导航和返回规则
- 左上角返回按钮只在当前网页存在历史页面时显示,只负责网页后退。
- 右上角关闭按钮始终显示,点击立即关闭当前 WebView 页面。
- Android 物理返回键优先返回网页历史。
- 没有网页历史时,物理返回键需要在一秒内再次按下才关闭页面。
- 默认菜单包含刷新、复制链接和在系统浏览器打开,不包含关闭页面。
## 导航栏与状态栏
```ts
openWebView({
source: { uri: 'https://example.com' },
navigationBar: {
background: {
gradient: ['#1769E0', '#55A8FF'],
gradientAngle: 90,
// 也可以使用 color 或 image
},
title: {
text: '渐变导航栏',
color: '#FFFFFF',
mode: 'fixed',
},
backButton: { color: '#FFFFFF' },
closeButton: { color: '#FFFFFF' },
},
statusBar: {
backgroundColor: '#1769E0',
contentStyle: 'light-content',
translucent: true,
},
})
```
网络背景图片异步加载,不会阻塞 `openWebView` 返回。
完整替换导航栏时使用 `navigationBar.render(context)`。自定义返回按钮应调用
`context.onBackPress()`,以保留统一的网页后退规则。
## 自定义菜单
```tsx
openWebView({
source: { uri: 'https://example.com' },
navigationBar: {
menu: {
visible: true,
items: [
{
id: 'feedback',
label: '问题反馈',
onPress({ navigationState }) {
openFeedback({ url: navigationState.url })
},
},
],
},
},
})
```
不需要菜单时设置 `menu.visible: false`
## 摄像头和麦克风
宿主先声明系统权限,然后为具体网页配置精确 Origin
```ts
openWebView({
source: { uri: 'https://verify.example.com/start' },
permissions: {
allowedOrigins: ['https://verify.example.com'],
camera: true,
microphone: true,
},
})
```
Android Manifest 示例:
```xml
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
```
Origin 必须包含协议和主机,跨域后的页面不会继承原页面授权。宿主需要自定义决策时:
```ts
permissions: {
allowedOrigins: ['https://verify.example.com'],
camera: true,
microphone: true,
onRequest(request) {
if (canUseMedia(request.origin)) request.grant()
else request.deny()
},
}
```
## 文件下载
```ts
openWebView({
source: { uri: 'https://example.com/files' },
downloads: {
auto: true,
destination: 'publicDownloads',
conflict: 'rename',
onProgress(progress) {
console.log(progress.percentage)
},
onComplete(result) {
console.log(result.filePath)
},
onError(url, error) {
console.warn(url, error)
},
},
})
```
默认保存到应用沙盒。保存到系统 Downloads 只在目标平台支持时生效。
## 宿主 Bridge
宿主与 H5 自行约定消息协议,通过 `bridge` 注入:
```ts
openWebView({
source: { uri: 'https://example.com' },
bridge: {
async onMessage(raw, context) {
const message = JSON.parse(raw)
if (message.method === 'close') {
context.close('h5_close', message.data)
return true
}
if (message.method === 'setTitle') {
context.updateNavigation({
title: { text: String(message.title ?? '') },
})
return true
}
return false
},
},
})
```
XWebView 不规定方法名、App ID、厂商、用户或业务参数。协议校验、权限和业务结果由宿主
自己的 Bridge 负责。
## 内嵌 WebView
不需要独立页面和内置导航栏时:
```tsx
import { XWebViewView } from '@xuqm/rn-xwebview'
<XWebViewView
config={{
source: { uri: 'https://example.com' },
}}
/>
```
内嵌模式由所在页面负责尺寸、导航和关闭交互。