Kann ich Parameter in berechneten Eigenschaften in Vue.Js übergeben?


198

Ist es möglich, Parameter in berechneten Eigenschaften in Vue.Js zu übergeben? Ich kann sehen, wenn Getter / Setter berechnet werden, können sie einen Parameter nehmen und ihn einer Variablen zuweisen. wie hier aus der Dokumentation :

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

Ist das auch möglich:

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

Wobei berechnete Eigenschaft ein Argument nimmt und die gewünschte Ausgabe zurückgibt. Wenn ich dies jedoch versuche, wird folgende Fehlermeldung angezeigt:

vue.common.js: 2250 Nicht gefangener TypeError: fullName ist keine Funktion (…)

Sollte ich in solchen Fällen Methoden anwenden?


4
Nein, Sie können keine Parameter an berechnete Eigenschaften übergeben. Ja, die Verwendung von Methoden ist der einfachste Weg.
Null

Antworten:


265

Höchstwahrscheinlich möchten Sie eine Methode verwenden

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

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

Längere Erklärung

Technisch können Sie eine berechnete Eigenschaft mit einem Parameter wie dem folgenden verwenden:

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

(Danke Unirgyfür den Basiscode dafür.)

Der Unterschied zwischen einer berechneten Eigenschaft und einer Methode besteht darin, dass berechnete Eigenschaften zwischengespeichert werden und sich nur ändern, wenn sich ihre Abhängigkeiten ändern. Eine Methode wird jedes Mal ausgewertet, wenn sie aufgerufen wird .

Wenn Sie Parameter benötigen, bietet die Verwendung einer berechneten Eigenschaftsfunktion in einem solchen Fall normalerweise keine Vorteile gegenüber einer Methode. Obwohl Sie damit die parametrisierte Getter-Funktion an die Vue-Instanz binden können, verlieren Sie das Caching, sodass Sie dort keinen wirklichen Gewinn erzielen. Tatsächlich können Sie die Reaktivität (AFAIU) unterbrechen. Weitere Informationen hierzu finden Sie in der Vue-Dokumentation https://vuejs.org/v2/guide/computed.html#Computed-Caching-vs-Methods

Die einzige nützliche Situation ist , wenn Sie haben einen Getter verwenden und müssen , um es parametrisiert. Diese Situation tritt beispielsweise in Vuex auf . In Vuex ist dies die einzige Möglichkeit, synchron parametrisierte Ergebnisse aus dem Speicher abzurufen (Aktionen sind asynchron). Daher wird dieser Ansatz in der offiziellen Vuex-Dokumentation für seine Getter https://vuex.vuejs.org/guide/getters.html#method-style-access aufgeführt


1
Mit <span v-text="fullName('Hi')"></span>stattdessen funktioniert auch.
SalchiPapa

2
Das Problem war, dass <span :text="message"></span>man nicht mehr für Vue 2.0 funktioniert, sondern stattdessen verwenden muss: <span v-text="message"></span>oder <span>{{ message }}</span>wie in diesem Codepen gezeigt: codepen.io/Ismael-VC/pen/dzGzJa
SalchiPapa

1
Du hast recht. Ich habe nicht bemerkt, dass dies in 2.0 geändert wurde. Danke für die Korrektur!
Damienix

4
Berechnete Eigenschaften verwenden die ES5-Getter-Syntax, die das Aufrufen mit Parametern nicht unterstützt (es gibt keine Klammern). Es handelt sich also um eine Einschränkung der Sprachebene, und so wird sie in Vue.js integriert.
Damienix

1
Entschuldigung für eine sehr späte Antwort @PedroMoreira, ich habe gerade etwas Zeit gefunden, dies zu analysieren. In der Tat haben Sie Recht, dass das, was ich geschrieben habe, nicht klar und durcheinander war :) Ich habe die Antwort korrigiert und mein Bestes getan, um sie neu zu formulieren, um sie klarer und genauer zu machen. Sie können mich wissen lassen, ob es jetzt klar ist. Vielen Dank.
Damienix

27

Sie können Methoden verwenden, aber ich bevorzuge es immer noch, berechnete Eigenschaften anstelle von Methoden zu verwenden, wenn diese keine Daten mutieren oder keine externen Auswirkungen haben.

Sie können auf diese Weise Argumente an berechnete Eigenschaften übergeben (nicht dokumentiert, aber von Betreuern vorgeschlagen, weiß nicht mehr, wo):

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

BEARBEITEN: Bitte verwenden Sie diese Lösung nicht, sie kompliziert nur den Code ohne Vorteile.


Es ist sehr hilfreich, wenn Sie eine Referenz angeben können. Das sollte funktionieren.
Saurabh

@saurabh Entschuldigung, es war eine Lösung für ein nicht wirklich beschreibendes Problem in Github, und ich kann es
momentan

Dies funktioniert für mich, aber das einzige, von dem ich kein Fan bin, ist die Tatsache, dass es eher eine Funktion als die eigentliche Eigenschaft zurückgibt, sodass die VueJS-Devtools die Ergebnisse nirgendwo anzeigen. Ich bin mir nicht sicher, ob dies typisch für berechnete Eigenschaften ist, aber es macht die Fehlerbehebung etwas schwieriger.
Nate Ritter

4
Wie geht es mit Caching um? Funktioniert es ordnungsgemäß, wenn sich der Parameter ändert?
Damienix

Ich glaube nicht, dass es irgendetwas in der Rückgabefunktion zwischenspeichern würde. Der Unterschied zu Methoden wäre rein konventionell (Methoden haben Wirkung, berechnete sind nur zum Abrufen)
Unirgy

8

Technisch gesehen können wir einen Parameter an eine berechnete Funktion übergeben, genauso wie wir einen Parameter an eine Getter-Funktion in vuex übergeben können. Eine solche Funktion ist eine Funktion, die eine Funktion zurückgibt.

Zum Beispiel in den Getter eines Geschäfts:

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

Dieser Getter kann den berechneten Funktionen einer Komponente zugeordnet werden:

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

Und wir können diese berechnete Funktion in unserer Vorlage wie folgt verwenden:

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

Wir können den gleichen Ansatz anwenden, um eine berechnete Methode zu erstellen, die einen Parameter verwendet.

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

Und verwenden Sie es in unserer Vorlage:

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

Davon abgesehen sage ich hier nicht, dass es der richtige Weg ist, Dinge mit Vue zu tun.

Ich konnte jedoch feststellen, dass die Ansicht ihren Inhalt automatisch mit den neuen Eigenschaften dieses Elements aktualisiert, wenn das Element mit der angegebenen ID im Geschäft mutiert ist (die Bindung scheint einwandfrei zu funktionieren).


Woah, das hat bei mir funktioniert, ohne Vuex zu verwenden. Ich würde auch gerne wissen, ob dies ein legitimer Weg ist, um berechnete Eigenschaften auszuführen.
yeahdixon

1
Dies funktioniert zwar, behandelt die berechnete Eigenschaft jedoch im Wesentlichen wie eine Methode. Das heißt, es verliert die Caching-Vorteile einer berechneten Eigenschaft. Es gibt also keinen tatsächlichen Gewinn, wenn dies gegenüber einer Methode verwendet wird. "Beachten Sie, dass Getter, auf die über Methoden zugegriffen wird, jedes Mal ausgeführt werden, wenn Sie sie aufrufen, und das Ergebnis nicht zwischengespeichert wird." Siehe vuex.vuejs.org/en/getters.html
James

@ james.brndwgn, aber ich bin mir ziemlich sicher, dass Methoden nicht erneut ausgeführt werden, wenn die zugrunde liegenden Daten geändert werden. Das ist alles was ich wirklich suche.
Alex

@Alex dann solltest du einen Watcher benutzen. vuejs.org/v2/guide/computed.html#Watchers
James

@ james.brndwgn Ich würde viel lieber eine berechnete Eigenschaft als einen Beobachter verwenden, wenn möglich. Ich habe nur Ihre Aussage in Frage gestellt: "Es gibt also keinen tatsächlichen Gewinn, wenn Sie dies gegenüber einer Methode verwenden." da es auch ohne Caching einen signifikanten Unterschied gibt.
Alex

4

Filter sind eine von Vue-Komponenten bereitgestellte Funktion, mit der Sie Formatierungen und Transformationen auf jeden Teil Ihrer dynamischen Vorlagendaten anwenden können.

Sie ändern weder die Daten einer Komponente noch etwas anderes, sondern wirken sich nur auf die Ausgabe aus.

Angenommen, Sie drucken einen Namen:

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>

Beachten Sie die Syntax zum Anwenden eines Filters: | filterName. Wenn Sie mit Unix vertraut sind, ist dies der Unix-Pipe-Operator, mit dem die Ausgabe einer Operation als Eingabe an die nächste übergeben wird.

Die Filter-Eigenschaft der Komponente ist ein Objekt. Ein einzelner Filter ist eine Funktion, die einen Wert akzeptiert und einen anderen Wert zurückgibt.

Der zurückgegebene Wert ist derjenige, der tatsächlich in der Vue.js-Vorlage gedruckt wird.


3

Sie können Argumente auch an Getter übergeben, indem Sie eine Funktion zurückgeben. Dies ist besonders nützlich, wenn Sie ein Array im Speicher abfragen möchten:

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

Beachten Sie, dass Getter, auf die über Methoden zugegriffen wird, jedes Mal ausgeführt werden, wenn Sie sie aufrufen, und das Ergebnis nicht zwischengespeichert wird.

Dies wird als method-style Access bezeichnet und ist in den Vue.js-Dokumenten dokumentiert .


2

Sie können Parameter übergeben, aber entweder ist dies keine vue.js-Methode oder die Art und Weise, wie Sie dies tun, ist falsch.

Es gibt jedoch Fälle, in denen Sie dies tun müssen. Ich werde Ihnen ein einfaches Beispiel zeigen, wie Sie mit getter und setter einen Wert an die berechnete Eigenschaft übergeben.

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

Und das Drehbuch

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

Wenn Sie auf die Schaltfläche klicken, übergeben wir den Namen 'Roland' an die berechnete Eigenschaft und in set() ändern den Namen von 'John Doe' in 'Roland'.

Im Folgenden finden Sie einen allgemeinen Anwendungsfall, wenn die Berechnung mit Getter und Setter verwendet wird. Angenommen, Sie haben den folgenden vuex-Shop:

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

Und in Ihrer Komponente möchten Sie v-modeleiner Eingabe hinzufügen , aber den Vuex-Speicher verwenden.

<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

Ich bin mir nicht ganz sicher, was Sie erreichen wollen, aber es sieht so aus, als ob Sie mit der Methode anstatt mit der Berechnung vollkommen in Ordnung sind!


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

wenn Sie verwenden möchten

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

1

Berechnet könnte man berücksichtigen, hat eine Funktion. Für ein Beispiel zur Valdiation könnten Sie also eindeutig Folgendes tun:

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

Welche Sie verwenden werden wie:

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

Denken Sie daran, dass Sie das für die Berechnung spezifische Caching immer noch verpassen werden.


0

Ja, es gibt Methoden zur Verwendung von Parametern. Wie bei den oben genannten Antworten ist es in Ihrem Beispiel am besten, Methoden zu verwenden, da die Ausführung sehr leicht ist.

Nur als Referenz können Sie in einer Situation, in der die Methode komplex und die Kosten hoch sind, die Ergebnisse wie folgt zwischenspeichern:

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

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

Hinweis: Wenn Sie dies verwenden, achten Sie auf den Speicher, wenn Sie mit Tausenden arbeiten

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.