Vue-router可以在新标签页中打开链接吗?

191

我有一个概览页面和一个详细子页面。所有的路由都是使用编程式导航实现的vue-router(v 0.7.x), 类似于这样:

this.$router.go({ path: "/link/to/page" })

然而,当我从概览页面跳转到子页面时,我需要像在<a>标签中添加_target="blank"一样在新标签页中打开子页面。

有什么方法可以做到这一点吗?


6
我认为这在Vue Router中是不可能的,你可以提取和构建你的URL,然后使用window.open(url, '_blank')来打开新窗口。 - Deepak
2
是的,他们正式说这是不可能的。谢谢。 - Tang Jiong
下面有一个可行的答案,你应该接受那个答案作为你问题的回复,你觉得呢? - Andres Felipe
1
我查看了所有的答案,唯一做的就是在我的router-link标签内添加了target="_blank"。但我不确定这是否是一个好的实践方法。而且我没有任何参数。 - greenridinghood
15个回答

349

我认为你可以像这样做:

const routeData = this.$router.resolve({name: 'routeName', query: {data: "someData"}});
window.open(routeData.href, '_blank');

这对我有用。

更新


关于组合 API:

import { useRouter } from 'vue-router'
const router = useRouter();
const routeData = router.resolve({name: 'routeName', query: {data: "someData"}});
window.open(routeData.href, '_blank');

4
对我来说,这似乎是最好的方法。你仍然可以使用 $router 来构建 URL,而无需将一些 hacky 字符串粘合在一起,然后使用 window 打开新标签页。+1 - John Smith
4
很遗憾,这种方法被一些默认的浏览器弹出窗口阻止程序所阻挡。 - Photonic
其中一个问题是window.open不会传递像tokens和其他头文件。 - Marcus
1
@Rafel,能否请您看一下与Github上的书籍“Full-Stack Vue.js 2 and Laravel 5”相关的Vue.JS问题,链接在这里https://stackoverflow.com/questions/59245577/laravel-vuejs-router-view-does-not-render-the-component?特别是看一下OP的EDIT:部分? - Istiaque Ahmed
此外,如果您不想打开已经打开的新选项卡,可以使用某些其他标识符将“目标”配置为所引用值的ID。例如:window.open(routeData.href, 'details ' + id); - Sham Fiorin
显示剩余2条评论

221

看起来在较新版本中已经可以实现了(Vue Router 3.0.1):

<router-link :to="{ name: 'fooRoute'}" target="_blank">
  Link Text
</router-link>

似乎不能通过参数传递,只能打开链接本身。对吗? - Gotts
2
@Gotts,你也可以传递参数和查询参数。下面是实现此功能的代码: <router-link :to="{ name: 'fooRoute',params:{param_var:'id_parameter'},query:{query_var:'query_params'}}" target="_blank"> 链接文本 </router-link> - Pushkar Shirodkar
1
请注意,这是针对<router-link>的内容,无法与this.$router.push()编程方式配合使用。 - jplindstrom
在router-link中添加target属性。这太棒了。如果我们需要在路由声明中使用逻辑,@Harish上面的答案似乎也可以工作。 - Gel
<router-link :to="{ name: 'fooRoute', params: { id: 132 } }"> 链接文本 </router-link> - Ahmed Aboud

25

对于那些想知道答案的人,答案是否定的。 请参见在Github上相关的问题

问:vue-router能否编程方式打开新标签页?

答:不行。请使用普通链接。


19
现在可以在v3版本的<router-link>标签中添加target="_blank"了。https://dev59.com/Z1kS5IYBdhLWcg3wVlXC#49654382 - thanksd
发现这个非常有用,而不是构建完整的URL并使用window.open。 - Sainath S.R
是的,对于Vue 3+,现在是可能的:https://dev59.com/Z1kS5IYBdhLWcg3wVlXC#49654382 - Sham Fiorin

21

如果您的路由定义与问题中要求的相同(路径为“/link/to/page”):

import Vue from 'vue'
import Router from 'vue-router'
import MyComponent from '@/components/MyComponent.vue';

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/link/to/page',
      component: MyComponent
    }
  ]
})

您可以按照以下方式解析您摘要页面中的URL并打开您的子页面:

<script>
export default {
  methods: {
    popup() {
      let route = this.$router.resolve({path: '/link/to/page'});
      // let route = this.$router.resolve('/link/to/page'); // This also works.
      window.open(route.href, '_blank');
    }
  }
};
</script>

当然,如果您已经给您的路由指定了名称,您可以通过名称解析URL:

routes: [
  {
    path: '/link/to/page',
    component: MyComponent,
    name: 'subPage'
  }
]

...

let route = this.$router.resolve({name: 'subPage'});

参考资料:


13

通常在项目中的某个地方,例如main.js或router.js

import Router from 'vue-router'

Router.prototype.open = function (routeObject) {
  const {href} = this.resolve(routeObject)
  window.open(href, '_blank')
}
在您的组件中:
<div @click="$router.open({name: 'User', params: {ID: 123}})">Open in new tab</div>

不是要打负面评价,但这对于Vue3来说可能会更好?因为在我的情况下,控制台/日志记录 this.$router.open 返回 undefined。 - Dexygen
这种方法是不被鼓励的,因为它会改变原型。你不能记录它,因为它不是规范的一部分。 - adi518

13

这对我起作用了-

let routeData = this.$router.resolve(
{
  path: '/resources/c-m-communities', 
  query: {'dataParameter': 'parameterValue'}
});
window.open(routeData.href, '_blank');

我修改了 @Rafael_Andrs_Cspedes_Basterio 的回答


10
只需要在你的路由文件中编写以下代码:
{
  name: 'Google',
  path: '/google',
  beforeEnter() {                    
                window.open("http://www.google.com", 
                '_blank');
            }
}

8

我认为最好的方法是简单地使用:

window.open("yourURL", '_blank');

*飞走了*


4
不够远 - Dexygen

6

如果您只关注相对路径,比如:/dashboard/about等,请查看其他答案。

如果您想要打开一个绝对路径,比如:https://www.google.com,并在新标签页中打开,您需要知道Vue Router不是用来处理这些的。

不过,他们似乎认为这是一个特性请求。 #1280。但在他们实现之前,



这里有一个小技巧,可以使用vue-router来处理外部链接。

  • 进入路由器配置文件(可能是router.js),并添加以下代码:
/* Vue Router is not meant to handle absolute urls. */
/* So whenever we want to deal with those, we can use this.$router.absUrl(url) */
Router.prototype.absUrl = function(url, newTab = true) {
  const link = document.createElement('a')
  link.href = url
  link.target = newTab ? '_blank' : ''
  if (newTab) link.rel = 'noopener noreferrer' // IMPORTANT to add this
  link.click()
}

现在,每当我们处理绝对URL时,都有一个解决方案。例如,要在新标签页中打开谷歌:
this.$router.absUrl('https://www.google.com)

请注意,每次我们在新标签页中打开另一页时,都必须使用noopener noreferrer

在此处阅读更多信息

或在此处阅读


在几乎所有设备上都能很好地运行,但在移动电话上却无法打开新窗口! - homerThinking

3
使用锚点标签最简单的方法如下:

示例代码:

<a :href="$router.resolve({name: 'posts.show', params: {post: post.id}}).href" target="_blank">
    Open Post in new tab
</a>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接