我想了解如何使用v-for和v-if‘s来编写重复的 bootstrap 语,而不是更简单的Vue-Logic.现在看来,当使用v-for和v-if一起使用时,不可能将索引号写入每个摘要以 Select 相应的值.

我想将下面示例中的"1"替换为v-if语句中的"{{n}}".那件事怎么可能?

<script setup lang="ts">
defineProps<{
  title: string,
  icon1?: string, // possible values: 'sun', 'moon' or 'misc'
  textBefore1: string,
  textColor1?: string,
  textAfter1?: string,
  icon2?: string, // possible values: 'sun', 'moon' or 'misc'
  textBefore2: string,
  textColor2?: string,
  textAfter2?: string,
  icon3?: string, // possible values: 'sun', 'moon' or 'misc'
  textBefore3: string,
  textColor3?: string,
  textAfter3?: string,
  icon4?: string, // possible values: 'sun', 'moon' or 'misc'
  textBefore4: string,
  textColor4?: string,
  textAfter4?: string,
}>()
</script>

<template>
  <div class="teaserContent">
    <div class="inner">
      <div class="positioning--top">
        <div class="titleContainer">
          <h2 class="title">{{ title }}</h2>
        </div>
      </div>
      <div class="positioningBottom">

        <div v-for="n in 4" class="cardElement">
          <!-- Repeat the teaser 4 times and replace the number with the index "n" -->
          <div class="iconContainer">
            <span v-if="icon1 === 'sun' || icon1 === 'moon' || icon1 === 'misc'" class="material-symbols-rounded icon">{{ icon1 === 'sun' ? 'sunny' : icon1 === 'moon' ? 'clear_night' : icon1 === 'misc' ? 'brightness_4' : 'clear_night' }}</span>
            <span v-else class="material-symbols-rounded icon">clear_night</span>
          </div>
          <div class="textContainer">
            <span class="text text--before">{{ textBefore1 }}</span>
            <span v-if="textColor1" class="text text--color">{{ ' ' + textColor1 }}</span>
            <span v-if="textAfter1" class="text text--after">{{ ' ' + textAfter1 }}</span>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
// style here ...
</style>

Edit: Added the working Solution

感谢Keyboard Corporation

CardTeaser.vue:

<script setup lang="ts">
import type {ICardTeaser} from "@/components/CardTeaser/CardTeaser.types";

interface Props {
  title: string,
  teasers: Array<ICardTeaser>,
}

const props = defineProps<Props>();

const getIcon = (icon: ICardTeaser["icon"]) => {
  if (icon === 'sun') {return 'sunny';}
  if (icon === 'misc') {return 'brightness_4';}
  return 'clear_night';
};
</script>

<template>
  <div class="teaserContent">
    <div class="inner">
      <div class="positioning--top">
        <div class="titleContainer">
          <h2 class="title">{{ title }}</h2>
        </div>
      </div>
      <div class="positioningBottom">
        <div v-for="(teaser, n) in props.teasers" v-bind:key="`cardElement-${n}`" class="cardElement">
          <div class="iconContainer">
            <span class="material-symbols-rounded icon">{{ getIcon(teaser.icon) }}</span>
          </div>
          <div class="textContainer">
            <span class="text text--before">{{ teaser.textBefore }}</span>
            <span v-if="teaser.textColor" class="text text--color">{{ ' ' + teaser.textColor }}</span>
            <span v-if="teaser.textAfter" class="text text--after">{{ ' ' + teaser.textAfter }}</span>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
// Styles here ...
</style>

CardTeaser.tyes.ts:

export interface ICardTeaser {
    textBefore: string;
    textColor?: string;
    textAfter?: string;
    icon?: 'sun' | 'moon' | 'misc';
}

带数据的模板实现:

<CardTeaser title="Card Teaser" :teasers="[
  {
    textBefore: 'Card 1',
    textColor: 'in color',
    textAfter: 'with more text',
    icon: 'sun',
  },
  {
    textBefore: 'Card 2',
    textColor: 'also in Color',
    icon: 'moon',
  },
  {
    textBefore: 'Card 3',
    textColor: 'in color',
    textAfter: 'and more text',
    icon: 'misc',
  },
  {
    textBefore: 'Card 4',
    textColor: 'with more color',
    textAfter: 'and other text',
  }
]"/>

(似乎我也可以为每张卡制作一个更小的模板,只需将它们放在CardTeaserContainer或其他什么东西中.)

推荐答案

不能在v-if中直接使用v-for中的迭代器变量n作为字符串,但可以通过创建一个根据索引返回正确属性的computed属性来实现这一点.

首先,将props 定义为对象数组:

defineProps({
 teasers: {
    type: Array,
    default: () => []
 },
})

teasers中的每个对象都应该具有属性icontextBeforetextColortextAfter.

然后,在您的模板中,使用v-for迭代teasers:

<div v-for="(teaser, n) in teasers" class="cardElement">
 <div class="iconContainer">
    <span v-if="teaser.icon === 'sun' || teaser.icon === 'moon' || teaser.icon === 'misc'" class="material-symbols-rounded icon">{{ teaser.icon === 'sun' ? 'sunny' : teaser.icon === 'moon' ? 'clear_night' : teaser.icon === 'misc' ? 'brightness_4' : 'clear_night' }}</span>
    <span v-else class="material-symbols-rounded icon">clear_night</span>
 </div>
 <div class="textContainer">
    <span class="text text--before">{{ teaser.textBefore }}</span>
    <span v-if="teaser.textColor" class="text text--color">{{ ' ' + teaser.textColor }}</span>
    <span v-if="teaser.textAfter" class="text text--after">{{ ' ' + teaser.textAfter }}</span>
 </div>
</div>

Typescript相关问答推荐

typescribe不能使用值来索引对象类型,该对象类型满足具有该值的另一个类型'

类型{...}的TypeScript参数不能赋给类型为never的参数''

如何将类型从变量参数转换为返回中的不同形状?

根据上一个参数值查找参数类型,也返回类型

如何通过TypeScript中的工厂函数将区分的联合映射到具体的类型(如类)?

使某些(嵌套)属性成为可选属性

ANGLE找不到辅助‘路由出口’的路由路径

在TypeScrip的数组中判断模式类型

在函数中打字推断记录的关键字

被推断为原始类型的交集的扩充类型的交集

react 路由Use RouteLoaderData类型脚本错误

TypeScrip:从对象中提取和处理特定类型的键

重载函数的T helper参数

三重融合视角与正交阵

完全在类型系统中构建的东西意味着什么?

是否可以将类型参数约束为不具有属性?

可以';t使用t正确地索引对象;联合;索引类型

React-跨组件共享功能的最佳实践

如何在TypeScript中声明逆变函数成员?

如何确定剧作家中给定定位器的值?