一、设置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前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。