My component has 2 props: link
and isExternal
. Depending on the latter, I'll wrap my template code either in a <NuxtLink
(equivalent of native Vue
<router-link>
) or in a <a>
element.
The code below achieves that by using twice the same template code - which is obviously atrocious.
Yet I can't think of a simple way to do it elegantly. Any idea?
<template>
<NuxtLink
v-if="!isExternal"
to="link"
>
<div
class="btn"
:style="{
'background-color': backgroundColor,
'color': textColor
}"
>
<img
v-if="image"
:src="image"
class="image"
>
<div>{{ text }}</div>
<svg-icon name="arrow-right" class="arrow" />
</div>
</NuxtLink>
<a
v-else
href="link"
target="_blank"
>
<div
class="btn"
:style="{
'background-color': backgroundColor,
'color': textColor
}"
>
<img
v-if="image"
:src="image"
class="image"
>
<div>{{ text }}</div>
<svg-icon name="arrow-right" class="arrow" />
</div>
</a>
</template>
You may use component
element like this:
<template>
<component
:is="computedTag"
v-bind="computedProps"
>
<div
class="btn"
:style="{
'background-color': backgroundColor,
'color': textColor
}"
>
<img
v-if="image"
:src="image"
class="image"
>
<div>{{ text }}</div>
<svg-icon name="arrow-right" class="arrow" />
</div>
</component>
</template>
<script>
export default {
props: ['link', 'isExternal'],
computed: {
computedTag() {
return this.isExternal ? 'a' : 'nuxt-link';
},
computedProps() {
return this.isExternal
? { href: this.link, target: '_blank' }
: { to: this.link };
},
},
};
</script>