How to open external links in a new window with VueJS, vue-router and router-link
On one of my webapps I need to open external links (such as https://kerkour.com
) in a new window but internal links (such as /about
) with vue-router
to provide a pleasant Single Page App experience.
In traditionnal HTML this is achieved with the target="_blank" rel="noopener"
attributes of the a
element.
Unfortunately, vue-router
's RouterLink
components do not support these props, so I've created a custom component. If the link's hostname is the same as the hostname of the webApp, then a RouterLink
is rendered, otherwise a <a target="_blank" rel="noopener"
element.
*my_link.vue
<template>
<router-link v-if="isInternal" :to="href">
<slot></slot>
</router-link>
<a v-else :href="href" target="_blank" rel="noopener">
<slot></slot>
</a>
</template>
<script lang="ts" setup>
import { computed, type PropType } from 'vue';
const props = defineProps({
href: {
type: String as PropType<string>,
required: true,
}
});
const isInternal = computed((): boolean => {
if (props.href.startsWith('http')) {
let url = null;
try {
url = new URL(props.href);
} catch (err) {
return false;
}
if (url.hostname != window.location.hostname) {
return false;
}
}
return true;
});
</script>
You can then use this component like that:
<template>
<!-- ... -->
<my-link href="/my-url" />
<!-- ... -->
</template>
<script lang="ts" setup>
import MyLink from '@/ui/components/my_link.vue';
// ...
<script>