web-dev-qa-db-fra.com

Lier la classe à une fente dans Vue.js 2

J'essaie de créer un composant réutilisable pour itérer sur les éléments, les filtrer et ajouter des classes à l'emplacement (si l'élément est pair, impair, premier, dernier etc.)

Voici mon composant réutilisable:

<template>
  <ul :class="classes">
    <slot
      v-for="(item, index) in filteredItems"
      :item="item"
      :class="{
        'first': index == 0,
        'odd': !(index % 2),
        'even': index % 2,
        'last': index == (filteredItems.length - 1)
      }"
    >
    </slot>
  </ul>
</template>

<script>
export default {
  props: ['items', 'classes'],
  data() {
    return {
      filteredItems: this.items.filter(item => item.active)
    };
  }
};
</script>

Et voici comment je l'utilise:

<component-list :classes="'some-class'" :items="category.products">
  <template scope="props">
    <product :product="props.item"></product>
  </template>
<component-list>

Tout fonctionne comme prévu, mais cela n'ajoute pas de classes à l'élément placé à l'intérieur.

Est-ce que je fais quelque chose de mal? Est-il même techniquement possible dans Vue.js 2 de faire quelque chose comme ça?

Merci pour toute aide ou suggestion!

8
Matúš Čongrády

Avec vuejs2, le style des emplacements a été supprimé comme indiqué ici

Le contenu inséré via nommé ne conserve plus l'attribut slot. Utilisez un élément wrapper pour les styler ou, pour les cas d'utilisation avancés, modifiez le contenu inséré par programmation à l'aide de fonctions de rendu.

La chose la plus simple suggérée consiste à utiliser un élément wrapper comme suit:

<template>
  <ul :class="classes">
    <slot>
      <div
      v-for="(item, index) in filteredItems"
      :item="item"
      :class="{
        'first': index == 0,
        'odd': !(index % 2),
        'even': index % 2,
        'last': index == (filteredItems.length - 1)
      }"
    >
    </div>
    </slot>
  </ul>
</template>
7
Saurabh

J'ai un autre moyen d'obtenir votre objectif, mais pas d'utiliser render, continuez d'utiliser slot.

Le composant réutilisable:

<template>
  <ul :class="classes">
    <slot
      v-for="(item, index) in filteredItems"
      :item="item"
      :_class="{
        'first': index == 0,
        'odd': !(index % 2),
        'even': index % 2,
        'last': index == (filteredItems.length - 1)
      }"
    >
    </slot>
  </ul>
</template>

<script>
export default {
  props: ['items', 'classes'],
  data() {
    return {
      filteredItems: this.items.filter(item => item.active)
    };
  }
};
</script>

utilise _class à class mot clé , donc Vue.js laissera _class comme propriété commune.

Alors dans votre utilisation:

<component-list :classes="'some-class'" :items="category.products">
  <template scope="{ item, _class }">
    <product :product="item" :class="_class"></product>
  </template>
<component-list>

Par la propriété scope, vous pouvez toujours obtenir _class à partir de la fente.

Après tout, utiliser render peut être plus concis. :)

1
TomIsion

Dans votre composant enfant, n'utilisez pas la balise d'emplacement, mais liez simplement les données d'emplacement à un élément normal.

Par exemple, disons que j'ai un composant appelé modal. Dans mes parents, j'ai ceci:

<modal>
    <h1 slot="title">My modal title</h1>
</modal>

Donc, avec une fente normale, mon composant enfant aurait le balisage suivant:

<slot name="title" class="this-class-will-not-get-added"></slot>

Mais cette classe ne sera pas ajoutée.

Au lieu de cela, nous pouvons faire ceci:

<h1 class="this-class-will-get-added">{{this.$slots.title['0'].children['0'].text}}</h1>
0
Felix Eve