target="_blank"默认不安全,因新页可通过window.opener劫持原页或致性能降级,必须搭配rel="noopener noreferrer"使用;合法值包括_self、_blank、_parent、_top及命名iframe。

target="_blank" 能打开新窗口,但默认会带来安全与性能隐患,必须配合 rel="noopener noreferrer" 使用,否则可能被恶意页面控制原页。
为什么 target="_blank" 默认不安全
浏览器在新标签页打开链接时,如果没加 rel 属性,新页面可通过 window.opener 访问原始页面的 window 对象——这意味着它能调用 location.replace() 劫持原页、读取历史记录,甚至触发性能降级(因为两个页面共享同一个进程)。
常见错误现象:
• 点开外部链接后,原页面卡顿明显
• 用户返回原页时发现地址被悄悄跳转了
• 控制台报错 Blocked a frame with origin "xxx" from accessing a cross-origin frame(其实是防御性拦截,但说明风险已存在)
- 必须写
rel="noopener":切断window.opener引用,防止劫持 - 建议加
noreferrer:不发送Referer头,保护来源隐私 - 注意兼容性:
noopener在 Chrome 49+、Firefox 52+、Safari 10.1+ 支持;旧版 Safari 需用rel="noopener noreferrer"兼容
a 标签中 target 的合法值有哪些
target 不只是 "_blank",不同值影响页面复用逻辑,选错会导致意外覆盖或打不开:
立即学习“前端免费学习笔记(深入)”;
-
target="_self":默认值,在当前标签页打开(显式写出来可提高可读性) -
target="_blank":新开标签页/窗口(行为由浏览器设置决定,非强制“窗口”) -
target="_parent":在父<iframe>中打开,父不存在则退化为_self -
target="_top":在顶层窗口打开,常用于 iframe 内跳出嵌套 -
target="my-frame-name":匹配页面中name属性为"my-frame-name"的<iframe>或<frame>
注意:target 值区分大小写,"_BLANK" 无效;IE 会忽略带空格或特殊字符的自定义名字。
Vue / React 中动态生成 a 标签要注意什么
框架里容易忽略 HTML 原生属性的语义和副作用,尤其当 href 来自用户输入或 API 时:
- 避免直接拼接:
`<a target="_blank" href="https://www.php.cn/link/b85b19cea2f0268e105f30d78f668250">`</a>—— 若url含恶意 JS 协议(如javascript:alert(1)),可能执行脚本 - 服务端或前端需校验协议:只允许
https?、mailto:、tel:等安全协议 - React 中用
rel="noopener noreferrer"是必须项,不是可选项;Vue 模板同理,别只写target="_blank" - 若用
<router-link>或<Link>,它们不支持target,必须退回原生<a>
示例(安全写法):
<a :href="safeUrl" target="_blank" rel="noopener noreferrer">外部链接</a>
移动端 Safari 对 target="_blank" 的特殊限制
iOS 16.4+ 的 Safari 默认禁用所有 target="_blank" 的新开页行为,除非满足以下任一条件:
- 事件由真实用户点击触发(不能是
click()模拟) - 链接有
rel="noopener"(仅noopener就够,noreferrer非必需) - 页面启用了
document.hasStorageAccess()权限(极少用)
所以测试时别只在桌面 Chrome 看效果;真机上点不动,八成是漏了 rel 或用了自动触发逻辑。
容易被忽略的一点:即使加了 rel,如果链接是通过 setTimeout 延迟 10ms 后再触发 click(),Safari 仍判定为非用户手势,新开页失败。











