base target仅对无target且为相对URL的链接生效,绝对URL、锚点、JS导航等均无视;它必须置于head最顶部且唯一,是HTML解析阶段的静态兜底规则,非跳转策略工具。

base target 属性只对未显式声明 target 的相对链接生效
浏览器不会因为写了 <base target="_self"> 就强制所有链接都走这个逻辑。它只兜底——当 <a> 或 <form> 标签上既没写 target,又用的是相对 URL(如 href="user/edit")时,才应用该值。绝对 URL(href="https://example.com")、javascript: 链接、锚点(href="#")、JS 导航(location.href)完全无视 <base target>。
常见误判场景:
- 以为加了
<base target="_blank">就能“统一外链新窗口”,结果发现href="https://xxx.com"仍留在当前页——这是正常行为,不是 bug - 在 Vue/React 中用
<router-link>或Link组件,它们根本不走 HTML 原生导航流程,<base>对其零影响 -
target=""看似“清空”,但语义上不算显式声明,仍会回退到<base>的值
必须放在 <head> 最顶部,且只能有一个
<base> 的作用是重置 HTML 解析器对后续所有相对 URL 的基准起点,所以它必须是 <head> 中第一个元数据类标签。放错位置(比如在 <meta> 后面),或 SSR 模板中 header 和 page 各 render 一个,都会导致静默失效或仅第一个生效。
典型翻车写法:
立即学习“前端免费学习笔记(深入)”;
-
<body><base target="_self"></body>—— 被忽略 -
<head><title>Page</title><base target="_self"></head>—— 多数浏览器仍接受,但不保证兼容性;应严格前置 - 服务端拼接时重复注入
<base>,控制台提示Multiple base elements detected. Only the first one is used.
_self 不等于“覆盖窗口”,而是“在当前浏览上下文中加载”
target="_self" 不代表强制刷新整个标签页。它的行为完全取决于当前环境:
- 顶层页面中点击:替换整个文档,效果类似“覆盖”
- 嵌在
<iframe>里:只替换该 iframe 内容,父页面不动 - 被嵌入第三方平台(如 CMS 预览框):若对方设了
sandbox或 CSP 限制,_top可能被拦截,但_self依然安全有效
真正想“确保留在当前页”,不要依赖 <base> 兜底,而应主动给关键链接加 target="_self",尤其当页面已存在 <base target="_blank">(常见于 CMS 主题)时,target="_self" 是唯一能明确抵消它的写法。
与 JS 动态控制的边界必须分清
<base target> 是纯 HTML 解析阶段的静态规则,对运行时行为无干预能力。以下情况它完全无效:
-
document.querySelector('a').click()触发的点击 -
window.open(url, '_blank')或location.assign() - fetch / import / Worker 构造的路径(这些走 JS 引擎,不经过 HTML 解析)
如果业务要求精细区分内外链(比如仅外链 _blank),<base> 不是解法。更可靠的做法是用脚本补全:
document.querySelectorAll('a[href]:not([target])').forEach(a => {
if (a.href.startsWith(location.origin)) {
a.target = '_self';
} else {
a.target = '_blank';
a.rel = 'noopener';
}
});
记住:<base> 是兜底机制,不是跳转策略工具。越想靠它“统一管理”,越容易在 iframe、SPA、微前端、CMS 模板等场景里踩坑。



















