Puis-je transmettre des paramètres dans les propriétés calculées dans Vue.Js

199

est-il possible de passer un paramètre dans les propriétés calculées dans Vue.Js. Je peux voir que lorsque les getters / setter utilisent le calcul, ils peuvent prendre un paramètre et l'affecter à une variable. comme ici de la documentation :

// ...
computed: {
  fullName: {
    // getter
    get: function () {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
      var names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}
// ...

Est-ce également possible:

// ...
computed: {
  fullName: function (salut) {
      return salut + ' ' + this.firstName + ' ' + this.lastName    
  }
}
// ...

Où la propriété calculée prend un argument et renvoie la sortie souhaitée. Cependant quand j'essaye ceci, j'obtiens cette erreur:

vue.common.js: 2250 TypeError non capturé: fullName n'est pas une fonction (…)

Dois-je utiliser des méthodes pour de tels cas?

Saurabh
la source
5
Non, vous ne pouvez pas transmettre de paramètres aux propriétés calculées. Oui, l'utilisation de méthodes est la façon la plus simple de le faire.
nils

Réponses:

266

Vous souhaitez probablement utiliser une méthode

<span>{{ fullName('Hi') }}</span>

methods: {
  fullName(salut) {
      return `${salut} ${this.firstName} ${this.lastName}`
  }
}

Explication plus longue

Techniquement, vous pouvez utiliser une propriété calculée avec un paramètre comme celui-ci:

computed: {
   fullName() {
      return salut => `${salut} ${this.firstName} ${this.lastName}`
   }
}

(Merci Unirgypour le code de base pour cela.)

La différence entre une propriété calculée et une méthode est que les propriétés calculées sont mises en cache et ne changent que lorsque leurs dépendances changent. Une méthode évaluera chaque fois qu'elle sera appelée .

Si vous avez besoin de paramètres, il n'y a généralement aucun avantage à utiliser une fonction de propriété calculée par rapport à une méthode dans un tel cas. Bien que cela vous permette d'avoir une fonction getter paramétrée liée à l'instance Vue, vous perdez la mise en cache donc pas vraiment de gain là-bas, en fait, vous pouvez casser la réactivité (AFAIU). Vous pouvez en savoir plus à ce sujet dans la documentation Vue https://vuejs.org/v2/guide/computed.html#Computed-Caching-vs-Methods

La seule situation utile est lorsque vous devez utiliser un getter et que vous devez le paramétrer. Cette situation se produit par exemple dans Vuex . dans Vuex, c'est le seul moyen d'obtenir de manière synchrone le résultat paramétré du magasin (les actions sont asynchrones). Ainsi, cette approche est répertoriée par la documentation officielle de Vuex pour ses getters https://vuex.vuejs.org/guide/getters.html#method-style-access

damienix
la source
1
Utiliser à la <span v-text="fullName('Hi')"></span>place, fonctionne également.
SalchiPapa
2
Le problème était que <span :text="message"></span>, ne fonctionne plus pour Vue 2.0, il faut utiliser à la place: <span v-text="message"></span>ou <span>{{ message }}</span>comme indiqué dans ce codepen: codepen.io/Ismael-VC/pen/dzGzJa
SalchiPapa
1
Vous avez raison. Je n'ai pas remarqué que cela avait été changé en 2.0. Merci pour la correction!
damienix
4
Les propriétés calculées utilisent la syntaxe getter ES5 qui ne prend pas en charge l'appel avec aucun paramètre (il n'y a pas de parenthèses). C'est donc une limitation au niveau de la langue et c'est ainsi qu'il est intégré dans Vue.js.
damienix
1
Désolé pour une réponse très tardive @PedroMoreira, je viens de trouver du temps pour analyser cela. En effet, vous avez raison de dire que ce que j'ai écrit n'était pas clair et confus :) J'ai corrigé la réponse et j'ai fait de mon mieux pour la reformuler pour la rendre plus claire et précise. Vous pouvez me faire savoir si c'est clair maintenant. Merci.
damienix
27

Vous pouvez utiliser des méthodes, mais je préfère toujours utiliser des propriétés calculées au lieu de méthodes, si elles ne modifient pas les données ou n'ont pas d'effets externes.

Vous pouvez passer des arguments aux propriétés calculées de cette façon (non documenté, mais suggéré par les responsables, ne vous souvenez pas où):

computed: {
   fullName: function () {
      var vm = this;
      return function (salut) {
          return salut + ' ' + vm.firstName + ' ' + vm.lastName;  
      };
   }
}

EDIT: Veuillez ne pas utiliser cette solution, elle ne fait que compliquer le code sans aucun avantage.

Unirgy
la source
Ce sera très utile si vous pouvez fournir une référence. Cela devrait fonctionner.
Saurabh
@saurabh désolé, c'était une solution pour un problème pas vraiment descriptif dans github, et je ne le trouve pas pour le moment ...
Unirgy
Cela fonctionne pour moi, mais la seule chose dont je ne suis pas fan est le fait qu'il retourne une fonction plutôt que la propriété réelle, donc les devtools VueJS ne montrent les résultats nulle part. Je ne sais pas si c'est typique des propriétés calculées, mais cela rend le dépannage un peu plus difficile.
Nate Ritter
4
Comment gère-t-il la mise en cache? Cela fonctionnera-t-il correctement lorsque le paramètre change?
damienix
Je ne pense pas que cela mettrait en cache quoi que ce soit dans la fonction de retour. La différence avec les méthodes serait purement conventionnelle (les méthodes ont un effet, les calculs sont uniquement pour la récupération)
Unirgy
8

Eh bien, techniquement parlant, nous pouvons passer un paramètre à une fonction calculée, de la même manière que nous pouvons passer un paramètre à une fonction getter dans vuex. Une telle fonction est une fonction qui renvoie une fonction.

Par exemple, dans les getters d'un magasin:

{
  itemById: function(state) {
    return (id) => state.itemPool[id];
  }
}

Ce getter peut être mappé aux fonctions calculées d'un composant:

computed: {
  ...mapGetters([
    'ids',
    'itemById'
  ])
}

Et nous pouvons utiliser cette fonction calculée dans notre modèle comme suit:

<div v-for="id in ids" :key="id">{{itemById(id).description}}</div>

Nous pouvons appliquer la même approche pour créer une méthode calculée qui prend un paramètre.

computed: {
  ...mapGetters([
    'ids',
    'itemById'
  ]),
  descriptionById: function() {
    return (id) => this.itemById(id).description;
  }
}

Et utilisez-le dans notre modèle:

<div v-for="id in ids" :key="id">{{descriptionById(id)}}</div>

Cela étant dit, je ne dis pas ici que c'est la bonne façon de faire les choses avec Vue.

Cependant, j'ai pu observer que lorsque l'élément avec l'ID spécifié est muté dans le magasin, la vue actualise son contenu automatiquement avec les nouvelles propriétés de cet élément (la liaison semble fonctionner très bien).

Stéphane Appercel
la source
woah donc cela a fonctionné pour moi, sans utiliser vuex. aimerait également savoir s'il s'agit d'un moyen légitime de faire des propriétés calculées.
yeahdixon
1
Bien que cela fonctionne, il traite essentiellement la propriété calculée de la même manière qu'une méthode. c'est-à-dire qu'il perd les avantages de mise en cache d'une propriété calculée. Donc, il n'y a pas de gain réel en utilisant cela sur une méthode. "Notez que les getters accessibles via des méthodes s'exécuteront chaque fois que vous les appelez, et le résultat n'est pas mis en cache." Voir vuex.vuejs.org/en/getters.html
James
@ james.brndwgn mais je suis presque sûr que les méthodes ne seront pas réexécutées lorsque les données sous-jacentes seront modifiées. C'est tout ce que je recherche vraiment.
Alex
@Alex, alors vous devriez utiliser un observateur. vuejs.org/v2/guide/computed.html#Watchers
James
@ james.brndwgn Je préfère de loin utiliser une propriété calculée plutôt qu'un observateur si possible. Je ne faisais que contester votre déclaration: "Donc, il n'y a aucun gain réel à utiliser cela par rapport à une méthode." car il existe une différence significative même sans mise en cache.
Alex
4

Filtres sont une fonctionnalité fournie par les composants Vue qui vous permettent d'appliquer une mise en forme et des transformations à n'importe quelle partie des données dynamiques de votre modèle.

Ils ne modifient pas les données d'un composant ou quoi que ce soit, mais ils n'affectent que la sortie.

Supposons que vous imprimez un nom:

new Vue({
  el: '#container',
  data() {
    return {
      name: 'Maria',
      lastname: 'Silva'
    }
  },
  filters: {
    prepend: (name, lastname, prefix) => {
      return `${prefix} ${name} ${lastname}`
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="container">
  <p>{{ name, lastname | prepend('Hello') }}!</p>
</div>

Remarquez la syntaxe pour appliquer un filtre, qui est | filterName. Si vous connaissez Unix, c'est l'opérateur de canal Unix, qui est utilisé pour passer la sortie d'une opération en entrée à la suivante.

La propriété filters du composant est un objet. Un seul filtre est une fonction qui accepte une valeur et renvoie une autre valeur.

La valeur renvoyée est celle qui est réellement imprimée dans le modèle Vue.js.

Diego Pereira
la source
3

Vous pouvez également passer des arguments aux getters en renvoyant une fonction. Ceci est particulièrement utile lorsque vous souhaitez interroger un tableau dans le magasin:

getters: {
  // ...
  getTodoById: (state) => (id) => {
    return state.todos.find(todo => todo.id === id)
  }
}
store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }

Notez que les accesseurs accessibles via des méthodes s'exécuteront chaque fois que vous les appelez, et le résultat n'est pas mis en cache.

On appelle la méthode de style d' accès et est inscrite sur la documentation Vue.js .

Vinicius Brasil
la source
2

Vous pouvez passer des paramètres mais ce n'est pas une manière vue.js ou la façon dont vous faites est incorrecte.

Cependant, il y a des cas où vous devez le faire.Je vais vous montrer un exemple simple en passant une valeur à une propriété calculée en utilisant getter et setter.

<template>
    <div>
        Your name is {{get_name}} <!-- John Doe at the beginning -->
        <button @click="name = 'Roland'">Change it</button>
    </div>
</template>

Et le script

export default {
    data: () => ({
        name: 'John Doe'
    }),
    computed:{
        get_name: {
            get () {
                return this.name
            },
            set (new_name) {
                this.name = new_name
            }
        },
    }    
}

Lorsque le bouton a cliqué, nous passons à la propriété calculée le nom «Roland» et set() nous changeons le nom de «John Doe» en «Roland».

Vous trouverez ci-dessous un cas d'utilisation courant lorsque le calcul est utilisé avec getter et setter. Disons que vous avez la boutique vuex suivante:

export default new Vuex.Store({
  state: {
    name: 'John Doe'
  },
  getters: {
    get_name: state => state.name
  },
  mutations: {
    set_name: (state, payload) => state.name = payload
  },
})

Et dans votre composant, vous voulez ajouter v-modelà une entrée mais en utilisant le magasin vuex.

<template>
    <div>
        <input type="text" v-model="get_name">
        {{get_name}}
    </div>
</template>
<script>
export default {
    computed:{
        get_name: {
            get () {
                return this.$store.getters.get_name
            },
            set (new_name) {
                this.$store.commit('set_name', new_name)
            }
        },
    }    
}
</script>
roli roli
la source
1

Je ne suis pas tout à fait sûr de ce que vous essayez de réaliser, mais il semble que vous serez parfaitement bien en utilisant la méthode au lieu du calcul!

Marek Urbanowicz
la source
1
computed: {
  fullName: (app)=> (salut)=> {
      return salut + ' ' + this.firstName + ' ' + this.lastName    
  }
}

quand tu veux utiliser

<p>{{fullName('your salut')}}</p>
Khalid Hasan
la source
1

Calculé pourrait être considéré comme ayant une fonction. Donc, pour un exemple sur la valdiation, vous pouvez clairement faire quelque chose comme:

    methods: {
        validation(attr){
            switch(attr) {
                case 'email':
                    const re = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
                    return re.test(this.form.email);
                case 'password':
                    return this.form.password.length > 4
            }
        },
        ...
    }

Que vous utiliserez comme:

  <b-form-input
            id="email"
            v-model="form.email"
            type="email"
            :state="validation('email')"
            required
            placeholder="Enter email"
    ></b-form-input>

Gardez à l'esprit que la mise en cache spécifique au calcul vous manquera toujours.

Baldráni
la source
0

Oui, il existe des méthodes pour utiliser les paramètres. Comme les réponses indiquées ci-dessus, dans votre exemple, il est préférable d'utiliser des méthodes car l'exécution est très légère.

Seulement pour référence, dans une situation où la méthode est complexe et le coût est élevé, vous pouvez mettre en cache les résultats comme ceci:

data() {
    return {
        fullNameCache:{}
    };
}

methods: {
    fullName(salut) {
        if (!this.fullNameCache[salut]) {
            this.fullNameCache[salut] = salut + ' ' + this.firstName + ' ' + this.lastName;
        }
        return this.fullNameCache[salut];
    }
}

Remarque: Lorsque vous utilisez cela, faites attention à la mémoire si vous avez affaire à des milliers

Isometriq
la source