5
votes

Comment définir une variable dans un modèle de vue?

Problème

J'ai besoin de stocker temporairement les résultats d'un appel de méthode dans des modèles Vue. C'est particulièrement courant dans les boucles, où je ne peux pas facilement utiliser les propriétés calculées.

getVehicleTypeData: function(vehicleType){
    let options = _.find(this.vehicleTypeOptions, (obj)=>{
      return obj.vehicleType==vehicleType;
    });

    return options;
}

Extrait de code Javascript:

<ul>
  <li v-for="vehicleType in vehicleTypes" :key="vehicleType">
    <h3>{{ vehicleType }}</h3>
    <div v-if="getVehicleTypeData(vehicleType)">
     {{ getVehicleTypeData(vehicleType).costPerMile }}<br>
     {{ getVehicleTypeData(vehicleType).costPerHour }}<br>
    </div>
  </li>
</ul>


0 commentaires

5 Réponses :


1
votes

Malheureusement, c'est impossible dans la version actuelle :(

Dans votre exemple, vous pouvez faire un calcul avec des valeurs calculées et l'utiliser.

<ul>
  <li v-for="vehicleType, idx in vehicleTypes" :key="vehicleType">
    <h3>{{ vehicleType }}</h3>
    <div v-if="vtData[idx]">
     {{ vtData[idx].costPerMile }}<br>
     {{ vtData[idx].costPerHour }}<br>
    </div>
  </li>
</ul>

...

computed: {
  vtData() {
    return this.vehicleTypes.map(vt => this.getVehicleTypeData(vt));
  }
}


0 commentaires

2
votes

Une option consiste à définir un composant. Vous pouvez lui transmettre la valeur dont vous avez besoin pour «stocker» comme accessoire, et il peut l'utiliser de plusieurs façons. C'est l'approche la plus Vue-ish.

Une autre option est d'encapsuler votre appel de fonction dans un tableau et d'utiliser v-for pour créer un alias pour celui-ci. Il s'agit davantage d'une optimisation hacky / paresseuse, mais ce n'est pas fragile, juste étrange à lire.

<script src="https://unpkg.com/vue@latest/dist/vue.js"></script>
<ul id="app" new>
  <li v-for="vehicleType in vehicleTypes" :key="vehicleType">
    <h3>{{ vehicleType }}</h3>
    <template v-for="data in [getVehicleTypeData(vehicleType)]">
      <div v-if="data">
       {{ data.costPerMile }}<br> {{ data.costPerHour }}<br>
      </div>
    </template>
  </li>
</ul>
new Vue({
  el: '#app',
  data: {
    vehicleTypes: [0, 1]
  },
  methods: {
    getVehicleTypeData(type) {
      return [{
        costPerMile: 10,
        costPerHour: 40
      }][type];
    }
  }
});


0 commentaires

2
votes

J'ai trouvé une solution à partir de quelques recherches, et je poste la réponse moi-même, mais je ne sais pas s'il existe d'autres meilleures solutions.

Extrait de code Javascript:

<Pass v-for="vehicleType in VehicleTypes" v-bind:key="vehicleType" :temp="getVehicleData(vehicleType)">
  <div slot-scope="{temp}">
    <div class="pannel">
        <h6>{{ vehicleType }}</h6>
        <p v-if="temp">
          Cost per mile: <strong>${{ temp.costPerMile }}</strong>, 
          Cost per hour: <strong>${{ temp.costPerHour }}</strong>, 
          Cost per day: <strong>${{ temp.costPerDay }}</strong>
        </p>
    </div>
  </div>
</Pass>

Extrait de modèle:

const Pass = {
  render() {
    return this.$scopedSlots.default(this.$attrs)
  }
}

export default {
  components: {
    Pass
  },
  data: function () {
    return {
      vehicleTypeOptions: [],
    }
  },
  methods: {
    getVehicleData: function(vehicleType){
      let option = _.find(this.vehicleTypeOptions, (obj)=>{
        return obj.vehicleType==vehicleType;
      });
      return option;
    },
    loadData: function(){
      // get data from server using API and set to vehicleTypeOptions
    }
  },
  mounted: function(){
    this.loadData();
  }
}


1 commentaires

Cette approche utilise également des créneaux horaires mais est moins verbeuse: dev.to / loilo / an-approach-to-vuejs-template-variables-5aik



3
votes

Vous pouvez simplement créer une propriété calculée qui fusionne le type obj dans le tableau vehiclesTypes.

<ul>
  <li v-for="vehicle of vehicles" :key="vehicle.value">
    <h3>{{ vehicle.value }}</h3>
    <div v-if="vehicle.type">
     {{ vehicle.type.costPerMile }}<br>
     {{ vehicle.type.costPerHour }}<br>
    </div>
  </li>
</ul>

Et vous pouvez faire:

computed: {

  vehicles() {
    return this.vehicleTypes.map(vehicle => {
       return {
         value: vehicle,
         type: { ...this.getVehicleTypeData(vehicle) }
       }
    })
  }

},

methods: {
  getVehicleTypeData(vehicleType){
    let options = _.find(this.vehicleTypeOptions, (obj)=>{
      return obj.vehicleType==vehicleType;
    });

    return options;
  }
}

Si vous suivez la logique, je suis sûr que cela fonctionnera. Bien que je ne connaisse pas les valeurs de vehiclesTypes, le code ci-dessus peut nécessiter des modifications.

J'espère que cela pourra vous aider.


0 commentaires

5
votes

Un moyen rapide de contourner les lacunes actuelles de Vue est d'utiliser la portée via v-for et une seule boucle. Un exemple, espérons-le, explicatif:

<v-list>
  <v-list-tile v-for="(module, idx) in modules">
    <template v-for="scope in [{ isLocked: someFunction(module)}]">
      <!-- any markup -->
      <v-list-tile-action v-if="scope.isLocked">
        <v-icon color="amber">lock</v-icon>
      </v-list-tile-action>
    </template>
  </v-list-tile>
</v-list>

L'élément ci-dessus fait l'affaire. Vous appelez votre fonction ( someFunction ) dans un tableau temporaire d'objets de taille 1, l'assignez à une propriété ( isLocked ), qui à son tour est affectée à une variable de portée ( scope ). Vous pouvez désormais accéder à tout ce que someFunction renvoie autant de fois que vous le souhaitez sans sacrifier les performances via scope.isLocked .


0 commentaires