Vue: Pengikatan acara bersyarat

Dibuat pada 31 Des 2017  ·  34Komentar  ·  Sumber: vuejs/vue

Masalah apa yang dipecahkan oleh fitur ini?

Saat ini jika kita ingin event handler berjalan secara kondisional, kita perlu menempatkan kondisi di event handler yang berarti bahwa event tersebut masih berlangganan dan kita membayar biaya alokasi memori untuk langganan event (addEventListener yang mendasari dan handler yang sesuai).

Dalam beberapa skenario ini adalah rasa sakit. Misalnya: katakan saya punya acara mouse (mouseover, mouseout) yang hanya bermakna pada perangkat yang benar-benar memiliki pointer/mouse dan tidak berarti pada perangkat seluler dan sentuh.

Saat ini, saya harus membuat langganan acara dan menambahkan kondisi di penangan (atau dalam hal ini bahkan tidak perlu karena acara tidak akan pernah menyala) TAPI saya masih memasang penangan ini dan mengalokasikan memori untuk mereka - yang terutama pada platform dengan memori terbatas seperti browser seluler adalah pemborosan.

Dengan membuat langganan acara itu sendiri bersyarat, kita dapat menghindari hal ini.

Seperti apa tampilan API yang diusulkan?

Dalam bentuknya yang paling sederhana, kami hanya dapat memeriksa handler yang disediakan dan jika falsy (atau hanya null) membuat hubungan pendek langganan acara dan TIDAK menerapkan operasi addEventListener yang mendasarinya.

Dengan cara ini kondisinya dapat muncul dalam deklarasi pengikatan acara itu sendiri:

<div @mouseover="condition ? handler : null" /> 
feature request has PR

Komentar yang paling membantu

@Kingwl yang masih menambahkan pendengar, yang ingin dihindari OP.

Saran @sqal sebenarnya adalah solusi yang valid, dan dapat disederhanakan menjadi:

<div v-on="{ mouseover: condition ? handler : null }">

Semua 34 komentar

@asiFarran

Saat ini, saya harus membuat langganan acara dan menambahkan kondisi di handler (atau dalam hal ini bahkan tidak perlu untuk itu karena acara tidak akan pernah menyala)

Sebenarnya ada cara lain yang sederhana untuk menangani kasus ini. Anda dapat meneruskan properti yang dihitung dengan objek pendengar Anda (atau nol jika kondisinya tidak terpenuhi) ke v-on , contoh: https://jsfiddle.net/c0Le92xe/

mungkin anda membutuhkan?
<div @mouseover="e => condition && handler(e)" />

@Kingwl yang masih menambahkan pendengar, yang ingin dihindari OP.

Saran @sqal sebenarnya adalah solusi yang valid, dan dapat disederhanakan menjadi:

<div v-on="{ mouseover: condition ? handler : null }">

Ya, solusi @sqal adalah solusi yang bagus dan dengan inlining seperti @yyx990803 , pertunjukan cukup dekat dengan apa yang ada dalam pikiran saya. Terima kasih!

Ini membawa saya ke masalah yang lebih dalam: Jika rebind terjadi (perubahan data) dan setelah evaluasi kondisi berubah (atau lebih umum jika objek spesifikasi acara yang diteruskan ke v-on berbeda), langganan acara yang ada tidak dibersihkan. Mereka masih (semoga) dibuang pada akhir siklus hidup komponen tetapi tidak ketika mereka 'seharusnya' yaitu ketika v-on rebind.

Ini mungkin kasus tepi yang tidak memiliki dampak besar untuk sebagian besar skenario tetapi hanya untuk referensi:

Dalam skenario saya, saya memiliki SVG yang kompleks dan perlu (opsional) melampirkan penangan mouse ke atas/keluar ke elemen tertentu berdasarkan beberapa logika.
Komponen ini berumur panjang dan perubahan data yang mendasari mengarah ke rebinding di mana saya perlu melampirkan event handler ke elemen yang berbeda di setiap rebind - maka saya perlu membuang langganan sebelumnya sehingga mereka tidak menjuntai yatim piatu dan sedih dan minum Penyimpanan.

Solusi tipikal - dan apa yang akhirnya akan saya lakukan - adalah menyiapkan satu pendengar acara 'tingkat atas' (per jenis acara) dan membiarkan acara menggelembung, tetapi untuk menjelaskan motivasi saya untuk mencobanya dengan cara Vue terlebih dahulu , ada sedikit pemrosesan yang harus terjadi di penangan saya yang saya maksudkan untuk menghitung sebelumnya dan memanggang langsung ke langganan acara itu sendiri sehingga penangan memiliki lebih sedikit yang harus dilakukan (respons lebih cepat dan lebih lancar) dan tidak dipanggil di semua untuk elemen yang tidak memerlukannya (sebagai lawan memfilter ini dengan mengandalkan kueri DOM di handler).

@VsevolodTrofimov intinya adalah untuk menghindari langganan acara terjadi sama sekali. Menerapkan kondisi di handler tidak memenuhi persyaratan ini. Harap perhatikan komentar di atas karena mereka memberikan resolusi yang memuaskan.

Saya menutup masalah ini untuk mencerminkan hal itu.

<div v-on="{ mouseover: condition ? handler : null }">

Apakah mungkin untuk meneruskan $event dan argumen lain ke pawang?

@pmayer
<div v-on="{ mouseover: condition ? $event => handler($event, arg) : null }">

Atau kari pawang dan gunakan

<div v-on="{ mouseover: condition ? handler(arg) : null }">

Dengan solusi yang disarankan

<div v-on="{ mouseover: condition ? handler : null }">

Apakah ada cara untuk menerapkan pengubah seperti ".stop.prevent"?

Hai @yyx990803 @VsevolodTrofimov

Solusi yang disarankan di sini (menggunakan v-on="{ mouseover: condition ? handler : null }" ) tidak benar-benar berfungsi dengan Vue terbaru.

Saya mendapatkan kesalahan ini:
Invalid handler for event "mouseover": got null

Jadi sepertinya Vue benar-benar mencoba memecat pawang alih-alih melepaskan ikatan acara .

@DawidMyslak
Ubah saja ke bawah dan itu akan berhasil

v-on="condition ? { mouseover: handler } : {}"

atau, jika pawang Anda disebut mouseover

v-on="condition ? { mouseover } : {}"

Bagus @pbastowski !

Terima kasih kawan!

Anda mungkin ingin membungkus dengan fungsi sebaris jika Anda memanggil pawang dengan data khusus. Sesuatu seperti ini

v-on="condition ? { mouseover: () => handler(somedata) } : {}"

Ini harus di Vue docs

@DawidMyslak
Ubah saja ke bawah dan itu akan berhasil

v-on="condition ? { mouseover: handler } : {}"

atau, jika pawang Anda disebut mouseover

v-on="condition ? { mouseover } : {}"

Apakah ada cara untuk menggabungkan ini dengan .once ?

Anda dapat menggunakan https://vuejs.org/v2/guide/render-function.html#Event -amp-Key-Modifiers

<button v-on="{ '~click': () => foo = new Date() }">Trigger only once</button>

Satu pertanyaan tentang ini, apakah akan ada kebocoran memori atau pendengar acara tidak dihapus ketika saya melakukan hal berikut, dan kondisinya berubah secara teratur?

<template>
<div  v-on="myListeners">
some content
</div>
</template>
<script>
...
computed: {
  myListeners() {
    return this.canExecute ? { click: () => this.$emit(...) } : {};
  },
},
...
</script>

Jadi singkatnya, apakah v-on menangani perubahan atau tidak?

@dietergeerts memang begitu.

Apakah ini berfungsi dengan acara asli? Saya tidak bisa membuatnya bekerja dengan keydown.native .

FYI. Sejak 2.6 (belum dirilis), Anda akan dapat menerapkan pengikatan peristiwa bersyarat sebagai berikut:

<div @[event]="handler" /> 

Sementara event diselesaikan menjadi null , pengikatan akan dihapus.

@Justineo Itu bagus, tapi saya baru saja mencoba versi beta dan sepertinya tidak berfungsi dengan pengubah (jenis apa pun). Apakah itu belum dilaksanakan? Apakah itu direncanakan?

@AlansCodeLog itu harus bekerja dengan semua pengubah. Jika tidak berfungsi, Anda harus membuka masalah baru dengan reproduksi.

@yyx990803 Oke, saya akan melihat apakah saya dapat mereproduksinya.

Saya telah membuka masalah di sini: #9417

mungkin anda membutuhkan?
<div @mouseover="e => condition && handler(e)" />

Versi JavaScript peramban

<div @mouseover="condition && handler(arguments[0])" />

@kieryk123 Bisakah Anda memberikan tautan CodeSandbox untuk dilihat?

Dalam kasus saya, saya mencoba melakukan ini pada elemen tombol yang dinonaktifkan (melalui Vuetify), tetapi ternyata Chrome tidak menjalankan acara yang diperlukan, dan elemen tersebut harus dibungkus dengan div atau serupa untuk menangkap acara tersebut.

Halo.
Saya mencoba melakukannya seperti ini, tetapi tidak berhasil.

// not working
v-on="{ [condition ? 'click.stop' : 'click'] : eventfunc }"
// or
// error
v-on="{ condition ? 'click.stop' : 'click' : eventfunc }"

Apakah ada solusi lain?
Terima kasih sebelumnya!

Berikut adalah trik untuk event asli (menggunakan Vue v2.6.11):

@mouseenter.native="condition && handler($event)"

<div @[event]="handler" />

@Justineo apakah sintaks ini ditambahkan ke Vue?
Saya tidak bisa membuatnya bekerja. Mungkin Anda dapat mengirim tautan ke dokumen tempat saya dapat membaca lebih lanjut tentangnya?

@proArtex terima kasih, bekerja untuk saya juga!
@keyup.delete="title.length === 0 && cancelTopicCreation()"

Pertanyaannya....mengapa?

@AndrewBogdanovTSS lihat biola ini https://jsfiddle.net/pbastowski/v0wt5qpo/27/

Sintaksnya berfungsi dengan baik untuk klik normal dan asli. Perhatikan bahwa event .native hanya tersedia pada komponen Vue dan bukan elemen HTML biasa.

@pbastowski string sederhana berfungsi, ya, tetapi yang saya butuhkan adalah dapat menyelesaikan nilai acara berdasarkan beberapa data reaktif, jadi saya memerlukan sesuatu seperti

<h2 @[() => someProp ? 'mouseup' : null]="alert('Normal click on an HTML element')">H2 Element - click it</h2>

dan sintaks seperti itu tidak berfungsi untuk saya

@AndrewBogdanovTSS Pindahkan saja logika Anda ke yang dihitung, lihat contoh yang diperbarui di sini https://jsfiddle.net/pbastowski/v0wt5qpo/63/

Apakah halaman ini membantu?
0 / 5 - 0 peringkat