如何根据条件将模板代码块包装在不同的元素中?

How to wrap a block of template code in different elements depending on a condition?

我的组件有 2 个属性:linkisExternal。根据后者,我会将我的模板代码包装在 <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>