The

tag is a great tool for navigating between the different pages of your Vue application, but it is not a tool when navigating to an external link, for which you should use a normal
tag. Maybe it’s just me, but a lot of times, I don’t bother to notice the difference. Other times, the link may be dynamic, that is, from a database or some user-provided data source. In this case, you have no idea whether the link is external or internal, and it is a pain to manually do v-if in every possible place to use the link.

Wouldn’t it be nice if a single component handled all the internal and external links? If you were anything like me, you’d be doing it right now.

Thankfully, extending the

component is as simple as wrapping it in your own custom component. Let’s get started! Let’s build an AppLink component that can handle any link, external or internal.

AppLink components

The first thing we should do is have our AppLink component accept all items that have the same router link. Why is that? This way our component’s “interface” can mimic the Router Link’s interface and we won’t have another API to remember. We can do this by importing the RouterLink from the Vue Router and dispersing its props into the props option of our component.

// AppLink.vue <script> import {RouterLink} from 'vue-router' export default{ props:{ ... RouterLink.props } } </script>Copy the code

In the template area, we can now create a router link label and bind all the items of our component to it. We also need to pass in the slots so that the text provided between the labels and the markup will appear in the router link.

// AppLink.vue
<template>
  <router-link v-bind="$props"><slot /></router-link>
</template>
Copy the code

As it stands now, we have handled all the internal links. What about external links? As mentioned earlier, the external link uses the A tag, so let’s add it to our template. Like a router link, we should pass the slot. Let’s bind href to the to property as well.

// AppLink.vue
<template>
  <a :href="to"><slot/></a>
  <router-link v-bind="$props"><slot/></router-link>
</template>
Copy the code

Cool, that goes for internal and external links! At this point, it may be worth noting that the above method only applies to Vue 3, which contains more than 1 root element).

Now, we just need a condition to tell us what kind of link we are providing to AppLink. We can determine this by creating a computed property called isExternal. First, we check to see if the value of our to item is a string. This is necessary because the to item might be an object, such as the one sometimes passed to router-link (i.e. :to=”{name:’RouteNameHere’}”). We then check to see if the string starts with an HTTP string. If both conditions are true, then we have an external link of our own.

// AppLink.vue
<script>
export default{
   //...
  computed:{
    isExternal(){
      return typeof this.to === 'string' && this.to.startsWith('http')
    }
  }
}
</script>
Copy the code

Router-link in the template area, we can now use the isExternal computed item in a V-if, when it is a, otherwise it will show true.

// AppLink.vue
<template>
  <a v-if="isExternal" :href="to"><slot/></a>
  <router-link v-else v-bind="$props"><slot/></router-link>
</template>
Copy the code

That’s it! We’re done! After registering the component globally in your application, you can now use it like this.

// Anywhere in your app
<AppLink :to="[external-or-internal-link]">Click Me</AppLink>
Copy the code

Further flexibility

Open in a new TAB

Let’s make the AppLink components more useful. For example, we want all external links to always open in a new TAB. Very simple. By adding a target=”_blank” to the TAB in the component, all external links to the entire web site now open in the new TAB.

// AppLink.vue
<template>
  <a ... target="_blank"><slot/></a>
  ...
</template>
Copy the code

This is the rule you might want to apply to most external links on your site, but if you want any particular external link to open in the same tag, you can use the HTML target attribute to tell the link instance to do so.

<AppLink :to="https://vueschool.io" target="_self">Vue School</AppLink>
Copy the code

Link security

When you use the target=”_blank” attribute to link to a page on another site, you end up exposing your site to performance and security issues.

  • The linked page may end up running in the same process as your page. Depending on the page being linked, this can slow down your own page.
  • Another page is also availablewindow.openerProperty to access the original pagewindow, causing safety problems.

For more details on this issue, see this informative post.

The solution to this problem is to provide an rel=”noopener” attribute for all your external link tags. But remember how painful it is to do so…… Oh, wait…… We don’t need to do that. We can add it once in our AppLink component, and that’s it.

// AppLink.vue
<template>
  <a ... rel="noopener"><slot/></a>
  ...
</template>
Copy the code

Unique style of external links

I’ve seen some sites have external links on their site that look a little different than links to other places on their own site. This can help users better understand how they ended up on a site they would not otherwise have visited. It can be anything from a subtle “external link” icon next to a link to a little warning below, such as “Link to a third party website.” Implementing this in our component is as simple as adding an external-link class to the A tag in our template, then changing its style with CSS, or adding an after sudo-Element. You can even add brand new elements to external links, such as an icon with a great font.

// AppLink.vue // (must have font awesome font included in project) <template> <a ... class="external-link"> <slot/> <i class="fas fa-external-link-alt"></i> </a> ... < span style = "box-sizing: border-box! Important; word-wrap: break-word! Important; Opacity: 0.7; } </style>Copy the code

conclusion

This is just one example of how you can extend router-link to suit both common and special situations. In addition, since all your links are encapsulated in a single component, you can easily update different aspects of all your links. Can you think of any other useful ways to improve our AppLink components? Do you use a similar approach in your app and have some wisdom to share? Please share your tips and tricks on extending the Vue Router link in the comments below!

To find out more about Vue Router 4, stay tuned for our free Vue Router 4 course! After registration, we will inform you as soon as the course is posted!

Where to start when choosing a vue.js course? What is the vue.js shop