Cara meneruskan parameter ke: klik di Svelte?


24

Mengikat fungsi ke tombol mudah dan langsung:

<button on:click={handleClick}>
    Clicks are handled by the handleClick function!
</button>

Tapi saya tidak melihat cara untuk mengirimkan parameter (argumen) ke fungsi, ketika saya melakukan ini:

<button on:click={handleClick("parameter1")}>
    Oh no!
</button>

Fungsi ini dipanggil memuat halaman, dan tidak pernah lagi.

Apakah mungkin sama sekali untuk melewatkan parameter ke fungsi yang dipanggil dari on:click{}?


EDIT:

Saya baru saja menemukan cara untuk melakukannya. Memanggil fungsi dari penangan inline berfungsi.

<button on:click={() => handleClick("parameter1")}>
    It works...
</button>

Itulah yang bahkan dokumen tidak sebutkan secara eksplisit. Tapi ya itulah jalan untuk saat ini saya pikir .. Sampai mereka datang dengan solusi yang berbeda ..
Manish

6
Ini bukan hack, ini cara kerjanya . Ini secara eksplisit disebutkan dalam tutorial svelte.dev/tutorial/inline-handlers
Rich Harris

3
Terima kasih atas komentar Anda! "Cara hacky" melakukannya tidak terlalu buruk, tapi saya berani mengatakan bahwa dokumen dan tutorial tidak terlalu eksplisit tentang hal ini. Mungkin hanya aku.
FelDev

Jawaban:


5

TL; DR

Hanya membungkus fungsi handler di fungsi lain, untuk keanggunan gunakan fungsi panah


Anda harus menggunakan deklarasi fungsi dan kemudian memanggil pawang dengan argumen. Fungsi panah elegan dan bagus untuk skenario ini.

MENGAPA saya perlu pembungkus fungsi lain?

Jika Anda hanya akan menggunakan pawang dan meneruskan parameternya, bagaimana tampilannya?

Mungkin kira-kira seperti ini:

<button on:click={handleClick("arg1")}>My awesome button</button>

Tapi ingat, handleClick("arg1")ini adalah bagaimana Anda menjalankan fungsi secara instan, dan itulah yang terjadi ketika Anda mengatakannya, itu akan dipanggil ketika eksekusi mencapai baris ini, dan tidak seperti yang diharapkan, ON BUTTON CLICK ...

Oleh karena itu, Anda memerlukan deklarasi fungsi, yang akan dipanggil hanya oleh peristiwa klik dan di dalamnya Anda memanggil penangan Anda dengan argumen sebanyak yang Anda inginkan.

<button on:click={() => handleClick("arg1", "arg2")}>
    My awesome button
</button>

Seperti @Rich Harris (penulis Svelte) tunjukkan dalam komentar di atas: Ini bukan hack, tetapi apa yang ditunjukkan dokumentasi juga dalam tutorial mereka: https://svelte.dev/tutorial/inline-handlers


12

Rich telah menjawab ini dalam komentar, begitu memuji dia, tetapi cara untuk mengikat parameter dalam penangan klik adalah sebagai berikut:

<a href="#" on:click|preventDefault={() => onDelete(projectId)}>delete</a>

function onDelete (id) {
  ...
}

Untuk memberikan detail ekstra bagi orang-orang yang juga kesulitan dengan hal ini, dan harus ada di dokumen jika tidak, Anda juga bisa mendapatkan acara klik dengan penangan seperti itu:

<a href="#" on:click={event => onDelete(event)}>delete</a>

function onDelete (event) {
  // if it's a custom event you can get the properties passed to it:
  const customEventData = event.detail

  // if you want the element, you guessed it:
  const targetElement = event.target
  ...
}

Mengapa Anda menggunakan tautan untuk tombol, padahal mereka tidak memiliki URL?
mikemaccana

Karena saya membangun PWA yang memiliki tautan sebagai cadangan, jadi ini lebih merupakan alasan kebiasaan. Itu bisa dengan mudah menjadi tombol.
Antony Jones

1

Saya membuatnya bekerja dengan ini:

<a href="#" on:click|preventDefault={onDelete.bind(this, project_id)}>delete</a>

function onDelete(id) {
}

1

Ini dia dengan metode debounce dan argumen peristiwa:

<input type="text" on:keydown={event => onKeyDown(event)} />


const onKeyDown = debounce(handleInput, 250);

async function handleInput(event){
    console.log(event);
}

-1

Tidak ada cara jelas yang disebutkan dalam dokumentasi dan solusi Anda akan berfungsi tetapi memang tidak terlalu elegan. Solusi pilihan saya sendiri adalah menggunakan currying di blok skrip itu sendiri.

const handleClick = (parameter) => () => {
   // actual function
} 

Dan dalam HTML

<button on:click={handleClick('parameter1')>
   It works...
</button>

Waspadalah terhadap kari

Seperti disebutkan dalam komentar, currying memiliki jebakannya. Yang paling umum yang dalam contoh di atas handleClick('parameter1')tidak akan dipecat ketika mengklik melainkan pada rendering, mengembalikan fungsi yang pada gilirannya akan diaktifkan onklik. Ini berarti bahwa fungsi ini akan selalu menggunakan 'parameter1' sebagai argumennya.

Oleh karena itu menggunakan metode ini hanya akan aman jika parameter yang digunakan adalah sejenis konstan dan tidak akan berubah setelah itu diberikan.

Ini akan membawa saya ke poin lain:

1) Jika parameter yang digunakan konstan, Anda juga bisa menggunakan fungsi terpisah

const handleParameter1Click = () => handleClick('parameter1');

2) Jika nilainya dinamis tetapi tersedia dalam komponen, ini masih dapat ditangani dengan fungsi mandiri:

let parameter1;
const handleParameter1Click = () => handleClick(parameter1);

3) Jika nilainya dinamis tetapi tidak tersedia dari komponen karena ini tergantung pada beberapa jenis ruang lingkup (misalnya: daftar item yang diberikan dalam blok #each) pendekatan 'hacky' akan bekerja lebih baik. Namun saya pikir akan lebih baik jika memiliki elemen-elemen daftar sebagai komponen sendiri dan kembali ke kasus # 2

Untuk menyimpulkan: kari akan bekerja dalam keadaan tertentu tetapi tidak dianjurkan kecuali Anda sangat sadar dan berhati-hati tentang cara menggunakannya.


3
Jangan lakukan ini! Cukup buat fungsi sebaris ( on:click={() => handleClick('parameter1')})
Rich Harris

1
Baru menyadari bahwa itu adalah proposal yang Anda tanggapi. Alasan saya menyarankan terhadap pendekatan currying ada dua - pertama, itu kurang segera jelas apa yang terjadi (orang cenderung menganggap bahwa handleClick('parameter1')itulah yang terjadi ketika klik terjadi , salah. Kedua, itu berarti bahwa pawang perlu rebound ketika parameter berubah, yang suboptimal. Saat ini, ada bug, yang berarti tidak berfungsi pula svelte.dev/repl/a6c78d8de3e2461c9a44cf15b37b4dda?version=3.12.1
Rich Harris

1
Benar, saya tidak menyadari bahwa bug itu tidak pernah saya temui. Kemudian lagi dalam basis kode yang saya kerjakan kita tidak pernah melewati parameter seperti ini, mereka hampir selalu objek dan yang tampaknya berfungsi: svelte.dev/repl/72dbe1ebd8874cf8acab86779455fa17?version=3.12.1
Stephane Vanraes

Saya memperbarui jawaban saya dengan beberapa perangkap currying dan refleksi lainnya. Terima kasih atas masukannya
Stephane Vanraes

Ah ya, itu akan bekerja dengan objek, selama referensi itu sendiri tidak berubah (dan bug yang mendasarinya akan diperbaiki pada waktunya juga)
Rich Harris
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.