So übergeben Sie Parameter an: Klicken Sie in Svelte?


24

Das Binden einer Funktion an eine Schaltfläche ist einfach und unkompliziert:

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

Aber ich sehe keine Möglichkeit, Parameter (Argumente) an die Funktion zu übergeben, wenn ich dies tue:

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

Die Funktion wird beim Laden der Seite aufgerufen und nie wieder.

Ist es überhaupt möglich, Parameter an die aufgerufene Funktion zu übergeben on:click{}?


BEARBEITEN:

Ich habe gerade einen hackigen Weg gefunden, es zu tun. Das Aufrufen der Funktion von einem Inline-Handler aus funktioniert.

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

Das haben selbst die Dokumente nicht explizit erwähnt. Aber ja, das ist der Weg für jetzt, denke ich. Bis sie eine andere Lösung finden.
Manish

6
Dies ist kein Hack, es funktioniert so . Es wird ausdrücklich im Tutorial svelte.dev/tutorial/inline-handlers
Rich Harris

3
Danke für deine Kommentare! Diese "hackige Art", es zu tun, ist doch nicht so schlecht, aber ich würde sagen, dass die Dokumente und das Tutorial diesbezüglich nicht sehr explizit sind. Vielleicht bin ich es aber auch.
FelDev

Antworten:


5

TL; DR

Wickeln Sie die Handlerfunktion einfach in eine andere Funktion ein. Verwenden Sie für Eleganz die Pfeilfunktion


Sie müssen eine Funktionsdeklaration verwenden und dann den Handler mit Argumenten aufrufen. Die Pfeilfunktion ist elegant und gut für dieses Szenario.

WARUM brauche ich einen anderen Funktions-Wrapper?

Wenn Sie nur den Handler verwenden und die Parameter übergeben würden, wie würde es aussehen?

Wahrscheinlich so etwas:

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

Aber denken handleClick("arg1")Sie daran, auf diese Weise rufen Sie die Funktion sofort auf, und genau das passiert, wenn Sie sie so ausdrücken. Sie wird aufgerufen, wenn die Ausführung diese Zeile erreicht, und nicht wie erwartet, AUF TASTE KLICKEN ...

Daher benötigen Sie eine Funktionsdeklaration, die nur vom click-Ereignis aufgerufen wird. Darin rufen Sie Ihren Handler mit so vielen Argumenten auf, wie Sie möchten.

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

Wie @Rich Harris (der Autor von Svelte) in den obigen Kommentaren betonte: Dies ist kein Hack, aber das zeigt die Dokumentation auch in ihren Tutorials: https://svelte.dev/tutorial/inline-handlers


12

Rich hat dies in einem Kommentar beantwortet, also danke ihm, aber die Art und Weise, Parameter in einem Klick-Handler zu binden, ist wie folgt:

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

function onDelete (id) {
  ...
}

Etwas mehr Detail für Menschen, die auch mit diesem Kampf, und es sollte in der Dokumentation, wenn dies nicht der Fall, können Sie auch das Click - Ereignis in eine solche Handler bekommen kann:

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

Warum verwenden Sie Links für Schaltflächen, wenn diese keine URL haben?
Mikemaccana

Weil ich PWAs baue, die Links als Fallbacks haben, ist das eher ein Grund der Gewohnheit. Es könnte leicht ein Knopf sein.
Antony Jones

1

Ich habe es damit zum Laufen gebracht:

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

function onDelete(id) {
}

1

Hier ist es mit einer Entprellungsmethode und einem Ereignisargument:

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


const onKeyDown = debounce(handleInput, 250);

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

-1

In der Dokumentation wird kein klarer Weg erwähnt, und Ihre Lösung wird funktionieren, ist aber in der Tat nicht sehr elegant. Meine eigene bevorzugte Lösung ist die Verwendung currying im Skript selbst blockieren.

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

Und im HTML

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

Vorsicht vor Curry

Wie in den Kommentaren erwähnt, hat Curry seine Tücken. Die häufigste, die im obigen Beispiel handleClick('parameter1')nicht beim Klicken, sondern beim Rendern ausgelöst wird und eine Funktion zurückgibt, die wiederum beim Klicken ausgelöst wird. Dies bedeutet, dass diese Funktion immer 'parameter1' als Argument verwendet.

Daher ist die Verwendung dieser Methode nur dann sicher, wenn der verwendete Parameter eine Konstante ist und sich nach dem Rendern nicht ändert.

Dies würde mich zu einem anderen Punkt bringen:

1) Wenn es sich um eine Konstante handelt, die einen Parameter verwendet, können Sie auch eine separate Funktion verwenden

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

2) Wenn der Wert dynamisch ist, aber innerhalb der Komponente verfügbar ist, kann dies weiterhin mit einer eigenständigen Funktion behandelt werden:

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

3) Wenn der Wert dynamisch ist, aber nicht in der Komponente verfügbar ist, da dies von einem bestimmten Bereich abhängt (z. B. einer Liste von Elementen, die in einem # jedes Block gerendert werden) , funktioniert der 'hacky'- Ansatz besser. Ich denke jedoch, dass es in diesem Fall besser wäre, die Listenelemente selbst als Komponente zu haben und auf Fall 2 zurückzugreifen

Fazit: Currying funktioniert unter bestimmten Umständen, wird jedoch nicht empfohlen, es sei denn, Sie wissen genau, wie Sie es verwenden.


3
Tu das nicht! Erstellen Sie einfach eine Inline-Funktion ( on:click={() => handleClick('parameter1')})
Rich Harris

1
Ich habe gerade festgestellt, dass dies der Vorschlag ist, auf den Sie geantwortet haben. Der Grund, warum ich von dem Currying-Ansatz abrate, ist zweierlei: Erstens ist weniger sofort klar, was passiert (die Leute neigen dazu anzunehmen, dass handleClick('parameter1')dies passiert, wenn der Klick falsch erfolgt. Zweitens bedeutet dies, dass der Handler bei jeder Änderung der Parameter zurückgebunden werden muss. Das ist suboptimal. Derzeit gibt es einen Fehler, der bedeutet, dass er sowieso nicht funktioniert. svelte.dev/repl/a6c78d8de3e2461c9a44cf15b37b4dda?version=3.12.1
Rich Harris

1
Es stimmt, ich war mir nicht bewusst, dass dieser Fehler selbst nie aufgetreten ist. Andererseits
Stephane Vanraes

Ich habe meine Antwort mit einigen Fallstricken und anderen Überlegungen aktualisiert. Vielen Dank für die Eingabe
Stephane Vanraes

Ah ja, es wird mit Objekten funktionieren, solange sich die Referenz selbst nicht ändert (und der zugrunde liegende Fehler zu gegebener Zeit ebenfalls behoben wird)
Rich Harris
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.