Posso passare parametri nelle proprietà calcolate in Vue.Js


199

è possibile passare questo parametro nelle proprietà calcolate in Vue.Js. Vedo che quando si calcolano i getter / setter, possono prendere un parametro e assegnarlo a una variabile. come qui dalla documentazione :

// ...
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]
    }
  }
}
// ...

È anche possibile questo:

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

Dove la proprietà calcolata accetta un argomento e restituisce l'output desiderato. Tuttavia, quando provo questo, ricevo questo errore:

vue.common.js: 2250 TypeError non rilevati: fullName non è una funzione (...)

Dovrei usare metodi per tali casi?


5
No, non è possibile passare parametri alle proprietà calcolate. Sì, l'utilizzo dei metodi è il modo più semplice per farlo.
nils

Risposte:


266

Molto probabilmente vuoi usare un metodo

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

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

Spiegazione più lunga

Tecnicamente puoi usare una proprietà calcolata con un parametro come questo:

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

(Grazie Unirgyper il codice di base per questo.)

La differenza tra una proprietà calcolata e un metodo è che le proprietà calcolate vengono memorizzate nella cache e cambiano solo quando cambiano le loro dipendenze. Un metodo valuterà ogni volta che viene chiamato .

Se hai bisogno di parametri, di solito non ci sono vantaggi nell'utilizzare una funzione di proprietà calcolata su un metodo in tal caso. Sebbene ti consenta di avere una funzione getter parametrizzata associata all'istanza Vue, perdi la memorizzazione nella cache, quindi in realtà non c'è alcun guadagno lì, infatti, potresti interrompere la reattività (AFAIU). Puoi leggere di più al riguardo nella documentazione di Vue https://vuejs.org/v2/guide/computed.html#Computed-Caching-vs-Methods

La situazione unica utile è quando si deve usare un getter e parametrizzato. Questa situazione si verifica ad esempio in Vuex . in Vuex è l'unico modo per ottenere in modo sincrono i risultati parametrizzati dal negozio (le azioni sono asincrone). Pertanto questo approccio è elencato nella documentazione ufficiale di Vuex per i suoi getter https://vuex.vuejs.org/guide/getters.html#method-style-access


1
Usando <span v-text="fullName('Hi')"></span>invece, funziona anche.
SalchiPapa,

2
Il problema era che <span :text="message"></span>, non funziona più per Vue 2.0, bisogna invece usare: <span v-text="message"></span>o <span>{{ message }}</span>come mostrato in questo codice: codepen.io/Ismael-VC/pen/dzGzJa
SalchiPapa

1
Hai ragione. Non ho notato che questo è stato modificato in 2.0. Grazie per la correzione!
Damienix,

4
Le proprietà calcolate utilizzano la sintassi getter ES5 che non supporta la chiamata con alcun parametro (non ci sono parentesi). Quindi è una limitazione a livello di lingua ed è così che è incorporato in Vue.js.
damienix,

1
Scusate la risposta molto tardi @PedroMoreira, ho appena trovato del tempo per analizzarlo. In effetti hai ragione sul fatto che ciò che ho scritto non è stato chiaro e confuso :) Ho risolto la risposta e ho fatto del mio meglio per riformularla per renderla più chiara e accurata. Puoi farmi sapere se è chiaro ora. Grazie.
damienix,

27

Puoi usare i metodi, ma preferisco ancora usare le proprietà calcolate invece dei metodi, se non stanno mutando i dati o non hanno effetti esterni.

È possibile passare argomenti alle proprietà calcolate in questo modo (non documentato, ma suggerito dai manutentori, non ricordare dove):

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

EDIT: Non utilizzare questa soluzione, complica solo il codice senza alcun vantaggio.


Sarà davvero utile se puoi fornire un riferimento. Questo dovrebbe funzionare.
Saurabh,

@saurabh mi dispiace che sia stata una soluzione per un problema non veramente descrittivo in github, e non riesco a trovarlo in questo momento ...
Unirgy

Questo funziona per me, ma l'unica cosa di cui non sono un fan è il fatto che restituisce una funzione anziché la proprietà effettiva, quindi i devtools di VueJS non mostrano i risultati da nessuna parte. Non sono sicuro che sia tipico delle proprietà calcolate, ma rende la risoluzione dei problemi un po 'più difficile.
Nate Ritter,

4
Come gestisce la memorizzazione nella cache? Funzionerà correttamente quando il parametro cambia?
damienix,

Non credo che memorizzerebbe nella cache qualcosa all'interno della funzione di ritorno. La differenza dai metodi sarebbe puramente convenzionale (i metodi hanno effetto, calcolati sono solo per il recupero)
Unirgy

8

Bene, tecnicamente parlando possiamo passare un parametro a una funzione calcolata, allo stesso modo in cui possiamo passare un parametro a una funzione getter in vuex. Tale funzione è una funzione che restituisce una funzione.

Ad esempio, nei getter di un negozio:

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

Questo getter può essere associato alle funzioni calcolate di un componente:

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

E possiamo usare questa funzione calcolata nel nostro modello come segue:

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

Possiamo applicare lo stesso approccio per creare un metodo calcolato che accetta un parametro.

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

E usalo nel nostro modello:

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

Detto questo, non sto dicendo qui che è il modo giusto di fare le cose con Vue.

Tuttavia, potrei osservare che quando l'articolo con l'ID specificato viene modificato nel negozio, la vista aggiorna automaticamente il suo contenuto con le nuove proprietà di questo articolo (l'associazione sembra funzionare correttamente).


woah quindi questo ha funzionato per me, non usando Vuex. vorrei anche sapere se questo è un modo legittimo per fare proprietà calcolate.
Sì,

1
Mentre funziona, essenzialmente tratta la proprietà calcolata come un metodo. cioè perde i benefici di memorizzazione nella cache di una proprietà calcolata. Quindi, non esiste alcun guadagno effettivo usando questo su un metodo. "Si noti che i getter accessibili tramite metodi verranno eseguiti ogni volta che li si chiama e il risultato non viene memorizzato nella cache." Vedi vuex.vuejs.org/en/getters.html
James

@James.brndwgn ma sono abbastanza sicuro che i metodi non verranno rieseguiti quando i dati sottostanti vengono modificati. Questo è tutto ciò che sto davvero cercando.
Alex,

@Alex allora dovresti usare un osservatore. vuejs.org/v2/guide/computed.html#Watchers
James

@ james.brndwgn Preferirei di gran lunga utilizzare una proprietà calcolata piuttosto che un osservatore, se possibile. Stavo solo mettendo in discussione la tua affermazione: "Quindi, non ci sono guadagni reali usando questo su un metodo." poiché esiste una differenza significativa anche senza memorizzazione nella cache.
Alex,

4

filtri sono una funzionalità fornita dai componenti Vue che ti consente di applicare la formattazione e le trasformazioni a qualsiasi parte dei dati dinamici del tuo modello.

Non modificano i dati di un componente o altro, ma influenzano solo l'output.

Supponi di stampare un nome:

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>

Notare la sintassi per applicare un filtro, che è | filtername. Se hai familiarità con Unix, questo è l'operatore pipe Unix, che viene utilizzato per passare l'output di un'operazione come input a quello successivo.

La proprietà filters del componente è un oggetto. Un singolo filtro è una funzione che accetta un valore e restituisce un altro valore.

Il valore restituito è quello effettivamente stampato nel modello Vue.js.


3

È inoltre possibile passare argomenti ai getter restituendo una funzione. Ciò è particolarmente utile quando si desidera eseguire una query su un array nel negozio:

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

Si noti che i getter accessibili tramite metodi verranno eseguiti ogni volta che li si chiama e il risultato non viene memorizzato nella cache.

Che è chiamato Metodo-Style di accesso ed è documentata la documentazione Vue.js .


2

È possibile passare parametri ma non è un modo vue.js o il modo in cui si sta facendo è sbagliato.

Tuttavia ci sono casi in cui è necessario farlo. Vi mostrerò un semplice esempio che passa valore alla proprietà calcolata usando getter e setter.

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

E la sceneggiatura

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

Quando il pulsante ha fatto clic, passiamo alla proprietà calcolata il nome "Roland" e dentro set() stiamo cambiando il nome da "John Doe" a "Roland".

Di seguito è riportato un caso d'uso comune quando calcolato con getter e setter. Supponi di avere il seguente negozio Vuex:

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

E nel tuo componente vuoi aggiungere v-modelun input ma usando l'archivio 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>

1

Non sono del tutto sicuro di ciò che stai cercando di ottenere, ma sembra che tu stia perfettamente bene usando il metodo anziché il calcolo!


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

quando vuoi usarlo

<p>{{fullName('your salut')}}</p>

1

Calcolato potrebbe essere considerato ha una funzione. Quindi per un esempio di valdiazione potresti chiaramente fare qualcosa del tipo:

    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
            }
        },
        ...
    }

Che userai come:

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

Tieni presente che ti mancherà comunque la memorizzazione nella cache specifica per il calcolo.


0

Sì, ci sono metodi per usare i parametri. Come le risposte sopra riportate, nel tuo esempio è meglio usare metodi poiché l'esecuzione è molto leggera.

Solo per riferimento, in una situazione in cui il metodo è complesso e il costo è elevato, è possibile memorizzare nella cache i risultati in questo modo:

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

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

nota: quando lo usi, fai attenzione alla memoria se hai a che fare con migliaia

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.