v2.5.0 为 RouterLink 恢复 H5 端浏览器链接的原生能力。通过
#ifdef H5条件编译,H5 端渲染为原生<a>标签(带真实href),恢复语义化、右键新标签页、地址识别、无障碍识别、href 原生行为等能力,同时保持普通左键仍由路由器导航(守卫链生效)。
前言
v2.3.1 为消除 H5 端 <navigator> 缺 url 属性导致的控制台错误,将 RouterLink 根元素改为 <view>。该方案解决了控制台报错,但 <view> 不是链接元素,H5 端因此失去了浏览器链接的原生能力:
- 链接语义和语义化支持
- 右键在新标签页打开
- 浏览器对链接地址的识别
- 无障碍工具对链接的识别
- href 带来的原生行为
v2.5.0 通过平台条件编译,在 H5 端渲染真实 <a> 标签解决此问题,同时保持其他平台行为不变。
一、方案
1. 平台条件编译
<!-- #ifdef H5 -->
<a class="router-link" :href="href" @click.stop="handleClick">
<slot />
</a>
<!-- #endif -->
<!-- #ifndef H5 -->
<navigator :hover-class="hoverClass" ... @click.stop="handleClick">
<slot />
</navigator>
<!-- #endif -->
- H5:渲染为原生
<a>(带href) - App / 小程序:渲染为
<navigator>(uni-app 原生导航组件),行为不变
2. useLink 提供响应式 href
const { href: resolvedHref, navigate } = useLink(props)
// H5 端 `<a>` 的 href:自动适配 hash 路由(# 前缀)
const href = computed(() => {
const fullPath = resolvedHref.value
// #ifdef H5
if (window.location.hash) {
return `#${fullPath}`
}
// #endif
return fullPath
})
3. 点击处理
async function handleClick(event?: unknown) {
// #ifdef H5
const e = event as MouseEvent
// 修饰键(ctrl/cmd/shift/alt)或中键点击保留浏览器原生行为(新标签页打开、另存为等)
if (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey || e.button !== 0) {
return
}
e.preventDefault()
// #endif
// 走路由器导航(守卫链生效)
await navigate()
}
二、恢复的原生能力
| 能力 | 说明 |
|---|---|
| 链接语义 | 页面中存在真实 <a> 标签,语义化结构完整 |
| 右键新标签页打开 | 右键菜单可正常弹出,"在新标签页打开"直接打开目标路由 |
| 浏览器地址识别 | 悬停时状态栏显示目标地址,浏览器识别为超链接 |
| 无障碍支持 | 屏幕阅读器等无障碍工具可正确识别为链接 |
| href 原生行为 | 修饰键(Ctrl/Cmd/Shift/Alt)或中键点击保留浏览器默认行为 |
三、脚本条件编译
handleClick 的修饰键判断与 href 的 hash 前缀逻辑均使用 #ifdef H5 包裹,非 H5 平台编译期剔除。原因:非 H5 平台(App/小程序)的点击事件对象没有 button / ctrlKey 等属性,若不做条件编译,e.button !== 0 会因
undefined !== 0 为 true 而误判为修饰键点击,导致导航被永久阻断。
四、验证结果
在 H5 端真实浏览器验证:
| 验证项 | 结果 |
|---|---|
| RouterLink 根元素 | 全部渲染为 <a>(非 view/navigator) |
| href 值 | 如 #/pages/detail/detail?id=link(带 hash 前缀) |
| 右键菜单 | defaultPrevented: false,原生菜单正常弹出 |
| 左键导航 | URL 变为 #/pages/detail/detail?__nav_id=...,守卫链完整执行无报错 |
五、升级指南
v2.5.0 完全向后兼容,无破坏性变更:
- 公开 API(Props / Emits / 导航行为)不变
- 非 H5 平台渲染
<navigator>,行为与之前完全一致 - H5 端从
<view>变为<a>,仅新增原生链接能力,导航仍走路由器(守卫链生效) - 新增的
href能力是增强,不要求使用方做任何改动
版本兼容性
| 功能 | v2.4.0 | v2.5.0 |
|---|---|---|
H5 端原生 <a> 渲染 | 不支持(<view>) | 支持 |
| 修饰键/中键原生行为 | 不支持 | 支持 |
| 右键"在新标签页打开" | 不支持 | 支持 |
| 非 H5 平台渲染 | <navigator> | <navigator>(不变) |
| 守卫链 | 支持 | 支持 |