WebView 里的一个链接或 window.open 并不会打开新标签页——它悄无声息地什么也不做。Android 默认 setSupportMultipleWindows(false),会忽略一切打开新窗口的请求;要让它生效,App 必须开启多窗口并实现 onCreateWindow 与 onCloseWindow,而多数 App 从未实现。iOS 上 WKWebView 的 createWebViewWithConfiguration 委托默认返回 nil,于是 target=_blank 被静默丢弃,除非 App 实现 WKUIDelegate;而开发者实现后,又常常新建第二个 WKWebView,其前进/后退历史与第一个完全脱节。宿主自有 runtime 提供统一窗口管理器:把弹窗映射为应用内标签页或一致的外部跳转,保持导航历史完整,绝不让链接静默失效。
Android:新窗口默认被忽略
Android 文档说得很直白:默认情况下系统会忽略打开新窗口的请求,无论是通过 JavaScript 还是 target 属性。要让 target=_blank 生效,App 必须调用 setSupportMultipleWindows(true) 并重写 onCreateWindow(以及用于清理的 onCloseWindow)。漏掉这个开关,onCreateWindow 永远不会被调用——点击没有导航、没有报错、什么都没有。在 App 生态里的实际结果,就是一长串「在新标签打开」的死链:在真实浏览器里能用,在 WebView 里凭空消失。
iOS:默认返回 nil 的委托
WKWebView 没有内置的标签页或窗口模型;当页面请求新的浏览上下文时,它通过 WKUIDelegate.createWebViewWithConfiguration 询问 App。默认实现返回 nil,意味着 target=_blank 与 window.open 被静默丢弃。开发者必须设置 uiDelegate 并实现该方法;常见的折中是把请求重新加载回同一个视图(丢失了本意的新标签语义),或新建一个全新的 WKWebView——它的前进/后退栈与原页面各自独立,用户被困住、找不到回去的路。
没有窗口管理器会失去什么
- 死链且无反馈。
target=_blank点击毫无反应,用户以为页面坏了。 - 历史断裂。 第二个 WebView 拥有独立的前进/后退栈,把用户与来源页割裂。
- 没有一致的外部链接策略。 有些链接应留在应用内,有些应交给系统浏览器;原生 WebView 没有规则。
- 丢失会话上下文。 本应继承登录或购物车状态的弹窗,在独立上下文里从头冷启动。
- 静默分化。 同一段 HTML 在 Safari 打开真正的标签,在嵌入视图里却什么也不做。
runtime 解法
宿主自有 runtime 在页面之下提供统一窗口管理器:把每一个新窗口请求映射到可预期的结果——共享导航历史与会话的应用内标签页,或清晰标注的、交给系统浏览器的外部跳转——并且绝不一声不响地吞掉链接。页面作者写标准的 target=_blank,runtime 按策略在两端一致地决定下一步发生什么。
| 维度 | WebView | 宿主自有 runtime |
|---|---|---|
| 新窗口默认 | 被忽略(Android)/ 委托返回 nil(iOS) | 映射为应用内标签或跳转 |
| Android 开关 | 需 setSupportMultipleWindows + onCreateWindow | runtime 接管 |
| iOS 路径 | 需 WKUIDelegate.createWebViewWithConfiguration | runtime 接管 |
| 导航历史 | 第二个视图中断裂 | 共享且完整 |
| 外部链接策略 | 无,各 App 自行猜 | 一致且可配置 |
| 静默死链 | 常见 | 绝不发生 |
浏览器把 target=_blank 当作一个承诺:一个新且可达的上下文。原生 WebView 把它当作一个可随意忽略的请求。runtime 恢复这一承诺——统一窗口管理器、完整历史、链接永远指向用户看得到的地方。
参考来源
- Android Developers — WebView「管理窗口」:新窗口请求默认被忽略,需 setSupportMultipleWindows + onCreateWindow — 默认丢弃弹窗。
- Stack Overflow — 不设置 setSupportMultipleWindows(true) 则 onCreateWindow 不会被调用 — 让链接失效的缺失开关。
- Apple Developer — WKUIDelegate createWebViewWithConfiguration:默认 nil 丢弃 target=_blank — 静默的 iOS 路径。
- Filip Němeček — 如何在 iOS 的 WKWebView 中打开 target=_blank 链接 — 为何链接无反应及委托修复。
- MDN — target=_blank 属性参考 — WebView 静默违背的 Web 标准。