问题描述
我的组件有 2 个道具:link
和 isExternal
。根据后者,我会将模板代码包装在 <NuxtLink
(相当于原生 Vue
<router-link>
)或 <a>
元素中。
下面的代码通过使用两次相同的模板代码实现了这一点——这显然是很糟糕的。
然而,我想不出一个简单的方法来优雅地做到这一点。有什么想法吗?
<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>
解决方法
您可以像这样使用 component
元素:
<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>