6.2 KiB
@xuqm/rn-xwebview
通用 React Native WebView 容器。1.1.0 只有三项正式入口:
<XWebViewHost />:应用根部挂载一次的全屏页面 Host。openWebView(config):从任意业务服务打开页面,返回该页面自己的 Handle。<XWebViewView config={...} />:不需要全屏导航栏时使用的内嵌浏览器内核。
SDK 不包含任何医网信、厂商、用户、平台、域名或业务 Bridge 定义。
安装
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-svg 含原生 ViewManager,必须由宿主直接声明并完成 React Native
autolink;它不能只作为 @xuqm/rn-xwebview 的传递依赖。缺少该直接依赖时,使用
SDK 内置导航图标的页面会在运行期报告找不到 RNSVGSvgViewAndroid。
@react-native-camera-roll/camera-roll 是可选 peer;只有需要把下载图片登记到系统相册
时才安装。
最小集成
import { XWebViewHost, openWebView } from '@xuqm/rn-xwebview'
export function App() {
return (
<>
<RootNavigation />
<XWebViewHost />
</>
)
}
const page = openWebView({
source: { uri: 'https://example.com' },
navigationBar: {
title: { text: '页面标题', mode: 'web' },
},
statusBar: {
translucent: true,
},
})
page.reload()
page.postMessage('hello')
page.suspend() // 临时展示宿主原生页面,WebView 实例和历史仍保留
page.resume()
page.close()
const result = await page.closed
Host 尚未挂载时请求最多等待 3 秒,超时以 host_unavailable 关闭。全局只能挂载一个
Host;Host 卸载会以 host_unmounted 关闭其全部页面。
分组配置
openWebView 与 XWebViewView 使用同一个 XWebViewConfig:
source:{uri, headers?}与{html, baseUrl?}二选一。navigationBar:标题、返回、关闭、菜单、纯色/渐变/图片背景或完整自定义渲染。statusBar:显隐、透明沉浸、背景和前景模式。behavior:Cookie、混合内容、外链决策、JS 注入、消息与生命周期回调。permissions:摄像头/麦克风白名单与可选宿主决策。downloads:自动/人工决策、目标目录、鉴权头、进度、完成和失败回调。bridge:由具体业务协议包提供;XWebView 只负责转发与页面上下文。
禁止恢复扁平的 url/title/showTopBar 双轨配置。
页面栈与系统返回
每次 openWebView 都生成独立页面和 Handle。页面栈只显示顶层页面,关闭后恢复下一层
页面及其导航状态。默认导航栏的左返回按钮常驻:存在网页历史时只执行网页后退,没有
历史时需要在 1 秒内再次点击才关闭当前页,第一次点击显示非阻塞提示。Android 物理
返回使用完全相同的规则。右侧关闭按钮常驻并立即关闭当前页。
宿主可以替换第一次返回时的提示;只有明确需要改变默认交互的宿主才应覆盖关闭模式或 间隔:
const page = openWebView({
behavior: {
hardwareBack: {
onFirstClosePress: () => showToast('再按一次退出当前页面'),
},
},
source: { uri: 'https://example.com' },
})
宿主需要短暂展示原生页面时调用 page.suspend(),原生页面结束后调用
page.resume();暂停不等于关闭,不触发 closed,也不创建第二份 WebView。
导航标题和显隐修改属于当前页面,不能污染下层页面。H5 隐藏原生导航栏但保留状态栏 时,Bridge 可以从页面上下文取得真实安全区高度。设置网络导航栏背景图片时,配置接收 后立即返回成功,图片由原生视图异步加载,不以图片探测或下载结果阻塞 H5 调用。
权限
SDK 不向 Manifest/Info.plist 注入敏感权限。宿主按启用能力声明,例如 Android:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
H5 调用 getUserMedia 时,XWebView 先检查页面配置和宿主决策,再在 Android 请求系统
权限,最后才继续 WebView 媒体请求。摄像头或麦克风必须同时启用能力并精确配置
allowedOrigins;当前文档跨域后不会沿用上一个 origin 的授权。未识别资源、未命中
白名单和 3 秒内未完成的自定义决策均拒绝:
permissions: {
allowedOrigins: ['https://example.com'],
camera: true,
microphone: true,
}
默认菜单包含刷新、复制链接和在系统浏览器中打开,不包含关闭页面;关闭始终使用右上角
常驻按钮。宿主可通过 navigationBar.menu.items 替换菜单,或通过
navigationBar.render 自定义返回、关闭和菜单的展示与点击行为。自定义导航栏若希望
保留 SDK 的统一返回规则,应调用渲染上下文的 onBackPress()。
下载与安全默认值
- 默认保存到 App 沙盒;
publicDownloads在 Android 使用沙盒落盘后登记到下载列表。 - URI 首屏 headers 自动复用于 HEAD 与文件下载,也可由
downloads.headers补充。 - Cookie 默认共享,第三方 Cookie 默认关闭。
- 混合内容默认
never;生产页面不得改为always。 http/https/about:blank在容器内打开;tel/sms/mailto交给系统;file/javascript/intent和未知 scheme 默认拒绝。- Bridge 异常不会形成未处理 Promise;宿主可通过
behavior.onBridgeError接收不含原始 payload 的错误信息。
迁移到 1.0.0
旧的 XWebViewScreen、XWebViewControl、openXWebView(navigate, flatConfig) 和
common 内的 WebView Bridge 已删除,不提供兼容壳。
迁移原则:
- 根部挂载一次
<XWebViewHost />。 - 扁平参数转换为上述分组配置。
- 全局 Control 改为保存本次
openWebView返回的页面 Handle。 - 业务 Bridge 单独作为
config.bridge注入,不进入 common 或 XWebView。 - 内嵌页面直接使用
<XWebViewView />,不再直接包装react-native-webview。
验证
pnpm --dir packages/xwebview typecheck
pnpm --dir packages/xwebview test
pnpm --dir packages/xwebview pack:check