Czy mogę przekazać parametry we właściwościach obliczeniowych w Vue.Js

198

czy można przekazać parametr we właściwościach obliczeniowych w Vue.Js. Widzę, że jeśli gettery / setter używają obliczeń, mogą wziąć parametr i przypisać go do zmiennej. jak tutaj z dokumentacji :

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

Czy to również możliwe:

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

Gdzie obliczona właściwość przyjmuje argument i zwraca pożądane dane wyjściowe. Jednak gdy próbuję tego, pojawia się ten błąd:

vue.common.js: 2250 Uncaught TypeError: fullName nie jest funkcją (…)

Czy powinienem stosować metody w takich przypadkach?

Saurabh
źródło
4
Nie, nie można przekazać parametrów do obliczonych właściwości. Tak, korzystanie z metod jest najłatwiejszym sposobem na zrobienie tego.
zero,

Odpowiedzi:

265

Najprawdopodobniej chcesz użyć metody

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

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

Dłuższe wyjaśnienie

Technicznie możesz użyć obliczonej właściwości z parametrem takim jak ten:

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

(Dzięki Unirgyza kod podstawowy za to.)

Różnica między obliczoną właściwością a metodą polega na tym, że obliczone właściwości są buforowane i zmieniają się tylko wtedy, gdy zmieniają się ich zależności. Sposób oceni za każdym razem to się nazywa .

Jeśli potrzebujesz parametrów, w takim przypadku zwykle nie ma korzyści z zastosowania obliczonej funkcji właściwości w stosunku do metody. Chociaż pozwala to na powiązanie sparametryzowanej funkcji gettera z instancją Vue, tracisz buforowanie, więc naprawdę nie zyskujesz tam, w rzeczywistości możesz przerwać reaktywność (AFAIU). Więcej na ten temat można przeczytać w dokumentacji Vue https://vuejs.org/v2/guide/computed.html#Computed-Caching-vs-Methods

Jedyna sytuacja jest przydatna, gdy trzeba użyć getter i trzeba mieć to parametryzowane. Taka sytuacja ma miejsce na przykład w Vuex . w Vuex jest to jedyny sposób, aby synchronicznie uzyskać sparametryzowany wynik ze sklepu (akcje są asynchroniczne). Dlatego podejście to jest wymienione w oficjalnej dokumentacji Vuex dla jego pobierających https://vuex.vuejs.org/guide/getters.html#method-style-access

damienix
źródło
1
Używanie <span v-text="fullName('Hi')"></span>zamiast tego również działa.
SalchiPapa,
2
Problem polegał na tym <span :text="message"></span>, że nie działa już dla Vue 2.0, należy zamiast tego użyć: <span v-text="message"></span>lub <span>{{ message }}</span>jak pokazano w tym codepen: codepen.io/Ismael-VC/pen/dzGzJa
SalchiPapa
1
Masz rację. Nie zauważyłem, że to się zmieniło w wersji 2.0. Dziękuję za poprawienie mnie!
damienix,
4
Obliczone właściwości używają składni gettera ES5, która nie obsługuje wywoływania jej z żadnymi parametrami (nie ma nawiasów). Jest to ograniczenie na poziomie języka i tak zostało włączone do Vue.js.
damienix
1
Przepraszam za bardzo późną odpowiedź @PedroMoreira, właśnie znalazłem trochę czasu, aby to przeanalizować. Rzeczywiście masz rację, że to, co napisałem, nie było jasne i pomieszane :) Naprawiłem odpowiedź i dołożyłem wszelkich starań, aby sformułować ją inaczej, aby była bardziej klarowna i dokładna. Możesz dać mi znać, jeśli teraz jest jasne. Dzięki.
damienix
27

Możesz używać metod, ale wolę nadal korzystać z obliczonych właściwości zamiast metod, jeśli nie mutują one danych lub nie mają efektów zewnętrznych.

W ten sposób możesz przekazać argumenty do obliczonych właściwości (nieudokumentowane, ale sugerowane przez opiekunów, nie pamiętam gdzie):

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

EDYCJA: Proszę nie używać tego rozwiązania, to komplikuje kod bez żadnych korzyści.

Unirgy
źródło
Bardzo pomocne będzie podanie referencji. To powinno działać.
Saurabh
@saurabh przepraszam, że było to rozwiązanie mało opisowego problemu w github i nie mogę go teraz znaleźć ...
Unirgy,
Działa to dla mnie, ale jedyne, czego nie jestem fanem, to fakt, że zwraca funkcję, a nie rzeczywistą właściwość, więc devtools VueJS nigdzie nie pokazują wyników. Nie jestem pewien, czy jest to typowe dla obliczonych właściwości, ale utrudnia to rozwiązywanie problemów.
Nate Ritter
4
Jak radzi sobie z buforowaniem? Czy będzie działał poprawnie po zmianie parametru?
damienix,
Nie sądzę, aby buforował coś w funkcji return. Różnica w stosunku do metod byłaby czysto konwencjonalna (metody mają skutek, obliczone są tylko do pobrania)
Unirgy
8

Cóż, technicznie rzecz biorąc, możemy przekazać parametr do funkcji obliczonej, tak samo jak możemy przekazać parametr do funkcji gettera w vuex. Taka funkcja jest funkcją, która zwraca funkcję.

Na przykład w pobierających sklep:

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

Ten moduł pobierający można zmapować na obliczone funkcje komponentu:

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

I możemy użyć tej obliczonej funkcji w naszym szablonie w następujący sposób:

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

Możemy zastosować to samo podejście do stworzenia metody obliczeniowej, która przyjmuje parametr.

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

I użyj go w naszym szablonie:

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

Biorąc to pod uwagę, nie mówię tutaj, że jest to właściwy sposób robienia rzeczy z Vue.

Widziałem jednak, że gdy element o określonym identyfikatorze zostanie zmutowany w sklepie, widok automatycznie odświeża jego zawartość dzięki nowym właściwościom tego elementu (wiązanie wydaje się działać dobrze).

Stéphane Appercel
źródło
woah, więc to zadziałało dla mnie, nie używając vuex. Chciałbym również wiedzieć, czy jest to legalny sposób wykonywania obliczonych właściwości.
yeahdixon,
1
Chociaż to działa, zasadniczo traktuje obliczoną właściwość tak samo jak metodę. tzn. traci korzyści z buforowania obliczonej właściwości. Tak więc nie ma rzeczywistego zysku przy użyciu tej metody. „Pamiętaj, że programy pobierające, do których dostęp uzyskuje się za pomocą metod, będą uruchamiane za każdym razem, gdy je wywołasz, a wynik nie jest buforowany”. Zobacz vuex.vuejs.org/en/getters.html
James
@ james.brndwgn, ale jestem prawie pewien, że metody nie zostaną uruchomione ponownie po zmianie podstawowych danych. To wszystko, czego naprawdę szukam.
Alex
@Alex to powinieneś używać obserwatora. vuejs.org/v2/guide/computed.html#Watchers
James
@ james.brndwgn Wolałbym raczej użyć obliczonej właściwości niż obserwatora, jeśli to możliwe. Kwestionowałem tylko twoje stwierdzenie: „Tak więc nie ma rzeczywistego zysku przy użyciu tej metody”. ponieważ istnieje znacząca różnica nawet bez buforowania.
Alex
4

Filtry to funkcjonalność zapewniana przez komponenty Vue, która umożliwia stosowanie formatowania i transformacji do dowolnej części dynamicznych danych szablonu.

Nie zmieniają danych komponentu ani niczego, ale wpływają tylko na wynik.

Powiedz, że drukujesz imię:

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>

Zwróć uwagę na składnię, aby zastosować filtr, którym jest | filterName. Jeśli znasz system Unix, jest to operator potoku Unix, który służy do przekazywania wyniku operacji jako danych wejściowych do następnego.

Właściwość Filtry komponentu to obiekt. Pojedynczy filtr to funkcja, która przyjmuje wartość i zwraca inną wartość.

Zwrócona wartość to ta, która jest faktycznie wydrukowana w szablonie Vue.js.

Diego Pereira
źródło
3

Możesz także przekazywać argumenty do pobierających, zwracając funkcję. Jest to szczególnie przydatne, gdy chcesz wykonać zapytanie do tablicy w sklepie:

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

Zwróć uwagę, że metody pobierające dostępne za pomocą metod będą uruchamiane za każdym razem, gdy je wywołasz, a wynik nie będzie buforowany.

To się nazywa metoda-Style dostęp i to jest udokumentowane na docs Vue.js .

Vinicius Brasil
źródło
2

Możesz przekazać parametry, ale albo nie jest to vue.js, albo sposób, w jaki to robisz, jest zły.

Są jednak przypadki, gdy trzeba to zrobić. Pokażę prosty przykład przekazywania wartości do obliczonej właściwości za pomocą gettera i settera.

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

I scenariusz

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

Po kliknięciu przycisku przechodzimy do obliczonej właściwości o nazwie „Roland” i in set() zmieniamy nazwę z „John Doe” na „Roland”.

Poniżej znajduje się typowy przypadek użycia, gdy obliczony jest używany z getter i setter. Załóżmy, że masz następujący sklep vuex:

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

W swoim komponencie chcesz dodać v-modeldo danych wejściowych, ale korzystając ze sklepu 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
źródło
1

Nie jestem do końca pewien, co próbujesz osiągnąć, ale wygląda na to, że wszystko będzie dobrze, używając metody zamiast obliczeń!

Marek Urbanowicz
źródło
1
computed: {
  fullName: (app)=> (salut)=> {
      return salut + ' ' + this.firstName + ' ' + this.lastName    
  }
}

kiedy chcesz użyć

<p>{{fullName('your salut')}}</p>
Khalid Hasan
źródło
1

Obliczone można rozważyć ma funkcję. Tak więc dla przykładu waldacji możesz wyraźnie zrobić coś takiego:

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

Którego będziesz używać jak:

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

Pamiętaj tylko, że nadal będziesz tęsknił za buforowaniem obliczeniowym.

Baldráni
źródło
0

Tak, istnieją metody używania parametrów. Podobnie jak w przypadku odpowiedzi podanych powyżej, w twoim przykładzie najlepiej stosować metody, ponieważ wykonanie jest bardzo lekkie.

Tylko w celach informacyjnych, w sytuacji, gdy metoda jest złożona, a koszt jest wysoki, możesz buforować wyniki w następujący sposób:

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

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

Uwaga: Korzystając z tego, uważaj na pamięć, jeśli masz do czynienia z tysiącami

Isometriq
źródło