Bisakah saya meneruskan parameter dalam properti yang dihitung dalam Vue.Js

199

apakah ini mungkin untuk melewatkan parameter dalam properti yang dihitung di Vue.Js. Saya bisa melihat ketika memiliki getter / setter menggunakan dihitung, mereka dapat mengambil parameter dan menetapkannya ke variabel. seperti di sini dari dokumentasi :

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

Apakah ini juga mungkin:

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

Di mana properti yang dihitung mengambil argumen dan mengembalikan output yang diinginkan. Namun ketika saya mencoba ini, saya mendapatkan kesalahan ini:

vue.common.js: 2250 Uncaught TypeError: fullName bukan fungsi (...)

Haruskah saya menggunakan metode untuk kasus seperti itu?

Saurabh
sumber
5
Tidak, Anda tidak dapat meneruskan parameter ke properti yang dihitung. Ya, menggunakan metode adalah cara termudah untuk melakukannya.
nils

Jawaban:

266

Kemungkinan besar Anda ingin menggunakan metode

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

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

Penjelasan yang lebih panjang

Secara teknis Anda dapat menggunakan properti yang dihitung dengan parameter seperti ini:

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

(Terima kasih Unirgyuntuk kode dasar untuk ini.)

Perbedaan antara properti yang dihitung dan metode adalah bahwa properti yang dihitung di-cache dan berubah hanya ketika dependensinya berubah. Suatu metode akan mengevaluasi setiap kali dipanggil .

Jika Anda memerlukan parameter, biasanya tidak ada manfaat dari menggunakan fungsi properti yang dihitung atas metode dalam kasus seperti itu. Meskipun ini memungkinkan Anda untuk memiliki fungsi pengambil parametrized terikat pada instance Vue, Anda kehilangan caching sehingga tidak benar-benar mendapatkan keuntungan di sana, pada kenyataannya, Anda dapat merusak reaktivitas (AFAIU). Anda dapat membaca lebih lanjut tentang ini di dokumentasi Vue https://vuejs.org/v2/guide/computed.html#Computed-Caching-vs-Methods

Satu-satunya situasi yang bermanfaat adalah ketika Anda harus menggunakan rajin dan rajin menggunakannya. Situasi ini terjadi misalnya di Vuex . di Vuex itu satu-satunya cara untuk secara sinkron mendapatkan hasil parametrized dari toko (tindakan async). Dengan demikian pendekatan ini didaftar oleh dokumentasi Vuex resmi untuk getternya https://vuex.vuejs.org/guide/getters.html#method-style-access

damienix
sumber
1
Menggunakan <span v-text="fullName('Hi')"></span>gantinya, juga berfungsi.
SalchiPapa
2
Masalahnya adalah bahwa <span :text="message"></span>, tidak lagi berfungsi untuk Vue 2.0, seseorang harus menggunakan sebagai gantinya: <span v-text="message"></span>atau <span>{{ message }}</span>seperti yang ditunjukkan dalam codepen ini: codepen.io/Ismael-VC/pen/dzGzJa
SalchiPapa
1
Kamu benar. Saya tidak melihat ini telah diubah pada 2.0. Terima kasih atas koreksinya!
damienix
4
Properti yang dikomputasi menggunakan sintaks getter ES5 yang tidak mendukung pemanggilan dengan parameter apa pun (tidak ada tanda kurung). Jadi ini adalah batasan tingkat bahasa dan itulah bagaimana itu dimasukkan ke dalam Vue.js.
damienix
1
Maaf atas respons @PedroMoreira yang sangat terlambat, saya baru saja menemukan waktu untuk menganalisis ini. Memang Anda benar bahwa apa yang saya tulis tidak jelas dan campur aduk :) Saya memperbaiki jawabannya dan melakukan yang terbaik untuk menguraikannya kembali agar lebih jelas dan akurat. Anda bisa memberi tahu saya jika sudah jelas sekarang. Terima kasih.
damienix
27

Anda dapat menggunakan metode, tetapi saya lebih suka masih menggunakan properti yang dikomputasi daripada metode, jika mereka tidak bermutasi data atau tidak memiliki efek eksternal.

Anda bisa memberikan argumen ke properti yang dihitung dengan cara ini (tidak didokumentasikan, tetapi disarankan oleh pengelola, tidak ingat di mana):

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

EDIT: Tolong jangan gunakan solusi ini, itu hanya mempersulit kode tanpa manfaat.

Unirgy
sumber
Akan sangat membantu jika Anda bisa memberikan referensi. Ini seharusnya bekerja.
Saurabh
@saurabh maaf itu adalah solusi untuk masalah yang tidak terlalu deskriptif di github, dan saya tidak dapat menemukannya sekarang ...
Unirgy
Ini bekerja untuk saya, tetapi satu-satunya hal yang saya bukan penggemar adalah kenyataan bahwa ia mengembalikan fungsi daripada properti yang sebenarnya, sehingga VueJS devtools tidak menunjukkan hasil di mana pun. Saya tidak yakin apakah itu tipikal untuk properti yang dihitung, tetapi itu membuat pemecahan masalah sedikit lebih sulit.
Nate Ritter
4
Bagaimana cara menangani caching? Apakah akan berfungsi dengan baik ketika parameter berubah?
damienix
Saya tidak percaya itu akan menembolok apa pun di dalam fungsi kembali. Perbedaan dari metode akan murni dari konvensi (metode memiliki efek, dihitung hanya untuk pengambilan)
Unirgy
8

Nah, secara teknis kita bisa melewatkan parameter ke fungsi yang dikomputasi, dengan cara yang sama kita bisa melewatkan parameter ke fungsi pengambil di vuex. Fungsi seperti itu adalah fungsi yang mengembalikan fungsi.

Misalnya, di getter toko:

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

Pembuat ini dapat dipetakan ke fungsi komponen yang dikomputasi:

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

Dan kita dapat menggunakan fungsi yang dihitung ini dalam templat kita sebagai berikut:

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

Kita dapat menerapkan pendekatan yang sama untuk membuat metode terkomputasi yang mengambil parameter.

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

Dan gunakan di template kami:

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

Makhluk ini berkata, saya tidak mengatakan di sini bahwa itu adalah cara yang tepat untuk melakukan sesuatu dengan Vue.

Namun, saya bisa mengamati bahwa ketika item dengan ID yang ditentukan dimutasi di toko, tampilan tidak me-refresh isinya secara otomatis dengan properti baru dari item ini (pengikatan tampaknya berfungsi dengan baik).

Stéphane Appercel
sumber
woah jadi ini bekerja untuk saya, tidak menggunakan vuex. juga ingin tahu apakah ini cara yang sah untuk melakukan properti yang dihitung.
yeahdixon
1
Meskipun ini berfungsi, pada dasarnya memperlakukan properti yang dikomputasi sama dengan metode. yaitu kehilangan manfaat caching dari properti yang dihitung. Jadi, tidak ada keuntungan sebenarnya menggunakan metode ini. "Perhatikan bahwa getter yang diakses melalui metode akan berjalan setiap kali Anda memanggilnya, dan hasilnya tidak di-cache." Lihat vuex.vuejs.org/en/getters.html
James
@ james.brndwgn tapi saya cukup yakin metode tidak akan dijalankan kembali ketika data yang mendasarinya diubah. Hanya itu yang saya cari.
Alex
@Alex maka Anda harus menggunakan pengamat. vuejs.org/v2/guide/computed.html#Watchers
James
@ james.brndwgn Saya lebih suka menggunakan properti yang dikomputasi daripada menonton jika mungkin. Saya hanya mempermasalahkan pernyataan Anda: "Jadi, sebenarnya tidak ada keuntungan menggunakan metode ini." karena ada perbedaan yang signifikan bahkan tanpa caching.
Alex
4

Filter adalah fungsi yang disediakan oleh komponen Vue yang memungkinkan Anda menerapkan pemformatan dan transformasi ke bagian mana pun dari data dinamis templat Anda.

Mereka tidak mengubah data komponen atau apa pun, tetapi mereka hanya memengaruhi output.

Katakanlah Anda sedang mencetak nama:

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>

Perhatikan sintaks untuk menerapkan filter, yaitu | filterName. Jika Anda terbiasa dengan Unix, itulah operator pipa Unix, yang digunakan untuk melewatkan output dari suatu operasi sebagai input ke yang berikutnya.

Properti filter dari komponen adalah sebuah objek. Filter tunggal adalah fungsi yang menerima nilai dan mengembalikan nilai lainnya.

Nilai yang dikembalikan adalah yang benar-benar dicetak dalam templat Vue.js.

Diego Pereira
sumber
3

Anda juga bisa memberikan argumen kepada getter dengan mengembalikan fungsi. Ini sangat berguna ketika Anda ingin menanyakan sebuah array di toko:

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

Perhatikan bahwa getter yang diakses melalui metode akan berjalan setiap kali Anda memanggilnya, dan hasilnya tidak di-cache.

Yang disebut Metode-Style Akses dan didokumentasikan pada docs Vue.js .

Vinicius Brasil
sumber
2

Anda dapat memberikan parameter tetapi itu bukan cara vue.js atau cara yang Anda lakukan salah.

Namun ada beberapa kasus ketika Anda perlu melakukannya. Saya akan menunjukkan kepada Anda contoh sederhana nilai kelulusan untuk properti yang dikomputasi menggunakan pengambil dan penyetel.

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

Dan skripnya

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

Ketika tombol diklik, kami meneruskan ke properti yang dihitung dengan nama 'Roland' dan in set() kami mengubah nama dari 'John Doe' menjadi 'Roland'.

Di bawah ini ada kasus penggunaan umum ketika dihitung digunakan dengan pengambil dan penyetel. Katakanlah Anda memiliki toko vuex follow:

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

Dan di komponen Anda, Anda ingin menambahkan v-modelinput tetapi menggunakan vuex store.

<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
sumber
1

Saya tidak sepenuhnya yakin apa yang ingin Anda capai tetapi sepertinya Anda akan baik-baik saja menggunakan metode alih-alih dihitung!

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

ketika ingin digunakan

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

Dihitung bisa dianggap memiliki fungsi. Jadi, untuk contoh valdiation, Anda dapat dengan jelas melakukan sesuatu seperti:

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

Yang akan Anda gunakan seperti:

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

Hanya perlu diingat bahwa Anda masih akan melewatkan caching khusus untuk dihitung.

Baldráni
sumber
0

Ya ada metode untuk menggunakan params. Seperti jawaban yang disebutkan di atas, dalam contoh Anda sebaiknya menggunakan metode karena eksekusi sangat ringan.

Hanya untuk referensi, dalam situasi di mana metode ini kompleks dan biayanya tinggi, Anda dapat men-cache hasil seperti:

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

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

Catatan: Saat menggunakan ini, hati-hati terhadap memori jika berurusan dengan ribuan

Isometriq
sumber