一、设置target=blank的基础用法
不少用Vue开发项目的同学,在做页面跳转时会碰到这么个需求——想让
target="_blank"时的路由模式与页面加载逻辑
Vue Router有history和hash两种路由模式,不同模式下target="_blank"的表现、配置要求不一样,得针对性处理。
history模式下的表现
如果项目用history模式(URL长这样:https://xxx.com/about),点击带target="_blank"的index.html),否则后端会返回404,导致新窗口空白。
举个例子,做后台管理系统时,点击“用户详情”在新窗口打开:
<router-link
:to="{name: 'UserDetail', params: {id: 123}}"
target="_blank"
>用户详情</router-link>
路由配置得有对应的动态路径:
const routes = [
{
path: '/user/:id',
name: 'UserDetail',
component: UserDetail
}
]
新窗口打开后,前端会解析URL里的/user/123,匹配到UserDetail组件,再通过this.$route.params.id拿到参数渲染页面。
hash模式下的表现
hash模式的URL带(比如https://xxx.com/#/about),点击hash不会触发后端请求(只有初始的index.html会被请求),所以新窗口加载时,前端直接解析后面的路由部分。
这种模式下,用<a href="#/about" target="_blank">更安全——href时的拼写错误。
安全风险与rel属性的搭配
当页面用target="_blank"打开新窗口时,存在“窗口劫持”漏洞:新窗口可以通过window.opener访问原窗口的location、document等对象,甚至篡改原页面。
解决方法是给rel="noopener noreferrer"属性:
<router-link to="/external-page" target="_blank" rel="noopener noreferrer" >外部页面</router-link>
rel="noopener":让新窗口的window.opener变为null,彻底切断对原窗口的访问;rel="noreferrer":在HTTP请求头中隐藏原页面的Referer信息,保护用户隐私。
现代浏览器对这两个属性支持很好,所以只要用了target="_blank",必须搭配rel属性,别让安全风险留隐患。
与直接使用<a>标签的区别
有人会问:既然target="_blank"和<a>标签行为很像,为啥不用原生<a>?这就得聊聊
路由激活状态自动管理
路由参数处理更智能
用to的对象语法传递params或query参数,自动拼接URL。
<router-link :to="{name: 'Post', params: {postId: 456}}">文章</router-link>
路由配置是path: '/post/:postId'时,URL会自动变成/post/456,如果用<a>标签,得自己拼接href="/post/456",参数多的时候很容易拼错。
单页应用的导航体验
动态控制target属性(场景化需求)
实际项目里,经常需要“条件式新窗口打开”——比如用户点“在新窗口打开”按钮时用target="_blank",普通点击则在当前窗口跳转,这时候可以通过动态绑定属性实现:
<template>
<router-link
:to="routePath"
:target="isNewWindow ? '_blank' : ''"
:rel="isNewWindow ? 'noopener noreferrer' : ''"
class="custom-link"
>
{{ linkText }}
</router-link>
</template>
<script>
export default {
data() {
return {
isNewWindow: false, // 控制是否新窗口打开
routePath: '/goods',
linkText: '商品页'
}
},
methods: {
toggleWindow() {
this.isNewWindow = !this.isNewWindow;
}
}
}
</script>
通过isNewWindow变量的切换,就能灵活控制跳转方式,这种写法在需要“用户自主选择跳转方式”的场景(比如文档类系统、多标签页管理)里特别实用。
常见问题与解决方案
用
新窗口打开后路由参数丢失?
如果用params传参,得确保路由配置的path包含动态段,比如想传orderId,路由得写成path: '/order/:orderId',否则params不会被拼到URL里,新窗口就拿不到参数。
如果不想把参数暴露在URL里(或参数非必填),可以改用query传参:
<router-link :to="{name: 'Order', query: {id: 123}}" target="_blank">订单页</router-link>
新窗口里通过this.$route.query.id就能拿到参数,更稳妥。
新窗口打开后页面是空白?
这种情况大概率是路由模式配置或服务端配置不对:
- 如果是
history模式,检查服务端是否配置了“所有请求返回index.html”,比如Nginx里要加try_files $uri $uri/ /index.html;,否则新窗口请求/order/123时,后端找不到资源就返回404。 - 如果是
hash模式,确保新窗口的URL带(比如https://xxx.com/#/order),如果用户手动输入不带的URL,前端路由解析不到,也会空白,所以尽量用生成URL,别让用户手动输入。
多个样式混乱?
实战案例:后台管理系统新窗口打开详情页
以电商后台的“订单列表→订单详情”场景为例,完整演示
配置路由(router/index.js)
import Vue from 'vue'
import VueRouter from 'vue-router'
import OrderList from '@/views/OrderList.vue'
import OrderDetail from '@/views/OrderDetail.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/order-list',
name: 'OrderList',
component: OrderList
},
{
path: '/order/:orderId',
name: 'OrderDetail',
component: OrderDetail
}
]
const router = new VueRouter({
mode: 'history', // 假设用history模式
base: process.env.BASE_URL,
routes
})
export default router
订单列表组件(OrderList.vue)
<template>
<div class="order-list">
<h2>订单列表</h2>
<ul>
<li
v-for="order in orders"
:key="order.id"
>
<router-link
:to="{name: 'OrderDetail', params: {orderId: order.id}}"
target="_blank"
rel="noopener noreferrer"
class="order-link"
>
订单号:{{ order.orderNumber }}
</router-link>
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
orders: [
{ id: 1, orderNumber: 'OD20240101' },
{ id: 2, orderNumber: 'OD20240102' }
]
}
}
}
</script>
<style scoped>
.order-link {
color: #42b983;
text-decoration: none;
}
.order-link:hover {
text-decoration: underline;
}
</style>
订单详情组件(OrderDetail.vue)
<template>
<div class="order-detail">
<h2>订单{{ orderId }}详情</h2>
<p>这里展示订单{{ orderId }}的具体信息...</p>
</div>
</template>
<script>
export default {
computed: {
orderId() {
return this.$route.params.orderId
}
},
created() {
// 这里可以发起接口请求,根据orderId获取订单详情
console.log('请求订单', this.orderId, '的详情数据')
}
}
</script>
<style scoped>
.order-detail {
padding: 20px;
}
</style>
这个案例里,点击订单号会在新窗口打开详情页,路由参数orderId能正确传递,页面也不会因为history模式配置错误而空白(前提是服务端配了fallback)。
总结与最佳实践
最后梳理下关键知识点和最佳实践,帮你少踩坑:
- 基础用法:给
加 target="_blank",但必须搭配rel="noopener noreferrer"防安全漏洞; - 路由模式:
history模式要配服务端fallback,hash模式要确保URL带; - 参数传递:优先用
query(URL可见,更稳妥)或确保params配合路由path的动态段; - 动态控制:通过
v-bind动态绑定target和rel,实现“条件式新窗口打开”; - 样式与状态:利用
的 router-link-active等class做高亮,或自定义class区分样式。
简单说,用
要是你在实际开发中碰到其他问题,比如多标签页通信、新窗口权限控制这些进阶场景,欢迎留言讨论,咱们一起拆解解决方案~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
code前端网



发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。