Come passare i parametri a on: fare clic su Svelte?


24

Associare una funzione a un pulsante è semplice e diretto:

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

Ma non vedo un modo per passare parametri (argomenti) alla funzione, quando faccio questo:

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

La funzione viene chiamata al caricamento della pagina e mai più.

È possibile affatto passare parametri da cui chiamare la funzione on:click{}?


MODIFICARE:

Ho appena trovato un modo bizzarro per farlo. La chiamata della funzione da un gestore in linea funziona.

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

Questo è ciò che nemmeno i documenti hanno menzionato esplicitamente. Ma sì, questo è il modo per ora penso .. Fino a quando non troveranno una soluzione diversa ..
Manish

6
Questo non è un trucco, è come funziona . È esplicitamente menzionato nel tutorial svelte.dev/tutorial/inline-handlers
Rich Harris,

3
Grazie per i tuoi commenti! Questo "modo bizzarro" di farlo non è poi così male, ma oserei dire che i documenti e il tutorial non sono molto espliciti al riguardo. Forse sono solo io, però.
FelDev,

Risposte:


5

TL; DR

Basta avvolgere la funzione di gestione in un'altra funzione, per l'eleganza utilizzare la funzione freccia


È necessario utilizzare una dichiarazione di funzione e quindi chiamare il gestore con argomenti. Le funzioni freccia sono eleganti e utili per questo scenario.

PERCHÉ ho bisogno di un altro wrapper di funzioni?

Se utilizzassi solo il gestore e passassi i parametri, come sarebbe?

Probabilmente qualcosa del genere:

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

Ma ricorda, handleClick("arg1")questo è il modo in cui invochi immediatamente la funzione, ed è esattamente ciò che sta accadendo quando la metti in questo modo, verrà chiamato quando l'esecuzione raggiunge questa linea e non come previsto, SU BOTTONE CLIC ...

Pertanto, è necessaria una dichiarazione di funzione, che verrà invocata solo dall'evento click e al suo interno si chiama il gestore con tutti gli argomenti che si desidera.

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

Come ha sottolineato @Rich Harris (l'autore di Svelte) nei commenti sopra: questo non è un trucco, ma è ciò che la documentazione mostra anche nei loro tutorial: https://svelte.dev/tutorial/inline-handlers


12

Rich ha risposto a questo in un commento, quindi merito a lui, ma il modo di associare i parametri in un gestore di clic è il seguente:

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

function onDelete (id) {
  ...
}

Per fornire alcuni dettagli extra per le persone che hanno anche problemi con questo, e dovrebbe essere nei documenti se non lo è, puoi anche ottenere l'evento click in un tale gestore:

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

Perché stai usando i collegamenti per i pulsanti, quando non hanno un URL?
mikemaccana,

Perché costruisco PWA che hanno collegamenti come fallback, quindi è più una ragione di abitudine. Potrebbe essere facilmente un pulsante.
Antony Jones,

1

Ho capito che funziona con questo:

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

function onDelete(id) {
}

1

Eccolo qui con un metodo debounce e un argomento evento:

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


const onKeyDown = debounce(handleInput, 250);

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

-1

Non c'è un modo chiaro menzionato nella documentazione e la tua soluzione funzionerà ma in effetti non è molto elegante. La mia soluzione preferita è usare il curry nel blocco di script stesso.

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

E in HTML

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

Attenzione al curry

Come menzionato nei commenti, il curry ha le sue insidie. Quello più comune che nell'esempio sopra handleClick('parameter1')non verrà attivato quando si fa clic ma piuttosto sul rendering, restituendo una funzione che a sua volta verrà attivata sul clic. Ciò significa che questa funzione utilizzerà sempre 'parametro1' come argomento.

Pertanto, l'utilizzo di questo metodo sarebbe sicuro solo se il parametro utilizzato è una costante di qualche tipo e non cambierà una volta eseguito il rendering.

Questo mi porterebbe ad un altro punto:

1) Se si utilizza una costante come parametro, è possibile utilizzare anche una funzione separata

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

2) Se il valore è dinamico ma disponibile all'interno del componente, questo potrebbe ancora essere gestito con una funzione autonoma:

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

3) Se il valore è dinamico ma non disponibile dal componente perché dipende da un tipo di ambito (es: un elenco di elementi renderizzati in un blocco #each) l' approccio 'hacky' funzionerà meglio. Tuttavia, penso che sarebbe meglio in quel caso avere gli elementi della lista come componente stessi e tornare al caso n. 2

Per concludere: il curry funzionerà in determinate circostanze ma non è raccomandato a meno che tu non sia ben consapevole e attento su come usarlo.


3
Non farlo! Basta creare una funzione inline ( on:click={() => handleClick('parameter1')})
Rich Harris,

1
Ho appena capito che era la proposta a cui stavi rispondendo. Il motivo per cui sconsiglio l'approccio al curry è duplice: in primo luogo, è immediatamente meno chiaro cosa sta succedendo (le persone tendono a supporre che handleClick('parameter1')sia ciò che accade quando si verifica il clic , in modo errato. In secondo luogo, significa che il gestore deve essere rimbalzato ogni volta che i parametri cambiano, che non è ottimale. Attualmente, c'è un bug, il che significa che non funziona comunque svelte.dev/repl/a6c78d8de3e2461c9a44cf15b37b4dda?version=3.12.1
Rich Harris

1
È vero, non ero a conoscenza di quel bug che non ho mai incontrato da solo. Poi di nuovo nel codebase su cui sto lavorando non passiamo mai parametri come questo, sono quasi sempre oggetti e sembra funzionare: svelte.dev/repl/72dbe1ebd8874cf8acab86779455fa17?version=3.12.1
Stephane Vanraes

Ho aggiornato la mia risposta con alcune insidie ​​al curry e altre riflessioni. Grazie per l'input
Stephane Vanraes,

Ah sì, funzionerà con gli oggetti, purché il riferimento stesso non cambi (e anche il bug sottostante verrà corretto a tempo debito)
Rich Harris
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.