Svelteでon:clickにパラメーターを渡す方法は?


24

関数をボタンにバインドするのは簡単で簡単です。

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

しかし、これを行うと、関数にパラメーター(引数)を渡す方法がわかりません。

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

この関数はページのロード時に呼び出され、二度と呼び出されません。

から呼び出された関数にパラメーターを渡すことはまったく可能on:click{}ですか?


編集:

私はそれを行うためのハッキーな方法を見つけました。インラインハンドラーからの関数の呼び出しは機能します。

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

それはドキュメントでさえ明示的に言及しなかったものです。しかし、はい、それは今のところ私が考える方法です。彼らが別の解決策を思い付くまで..
Manish

6
これはハックではなく、動作方法です。これは、明示的にチュートリアルで述べていますsvelte.dev/tutorial/inline-handlers
リッチ・ハリス

3
コメントしてくれてありがとう!結局のところ、これを行う「ハッキーな方法」はそれほど悪くありませんが、ドキュメントやチュートリアルはこれについてあまり明確ではありません。多分それは私だけです。
FelDev

回答:


5

TL; DR

ハンドラー関数を別の関数でラップするだけで、エレガントな矢印関数が使用されます


関数宣言を使用して、引数を指定してハンドラーを呼び出す必要があります。矢印関数はエレガントで、このシナリオに適しています。

なぜ別の関数ラッパーが必要なのですか?

ハンドラーだけを使用してパラメーターを渡す場合、どのように見えますか?

おそらくこのようなもの:

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

しかし、handleClick("arg1")これは関数を瞬時に呼び出す方法であり、これをこの方法で配置すると何が起こっているかを思い出してください。実行がこの行に到達したときに呼び出され、予想どおりON BUTTON CLICK ...ではありません。

したがって、関数宣言が必要です。これは、クリックイベントによってのみ呼び出され、その中で、必要な数の引数を使用してハンドラーを呼び出します。

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

@Rich Harris(Svelteの作者)が上記のコメントで指摘したように:これはハックではありませんが、ドキュメントが彼らのチュートリアルでも示しているものです:https : //svelte.dev/tutorial/inline-handlers


12

リッチはコメントでこれに答えたので、彼の功績ですが、クリックハンドラーでパラメーターをバインドする方法は次のとおりです。

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

function onDelete (id) {
  ...
}

これにも苦労している人に追加の詳細を提供し、そうでない場合はドキュメントに記載する必要がある場合は、そのようなハンドラーでクリックイベントを取得することもできます。

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

URLがないボタンにリンクを使用するのはなぜですか?
mikemaccana

私はリンクをフォールバックとして持つPWAを構築しているので、それが習慣の理由です。それは簡単にボタンになります。
アントニージョーンズ

1

私はそれをこれで動作させました:

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

function onDelete(id) {
}

1

ここでは、デバウンスメソッドとイベント引数を使用しています。

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


const onKeyDown = debounce(handleInput, 250);

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

-1

ドキュメントに明記されている明確な方法はなく、ソリューションは機能しますが、実際には非常にエレガントではありません。私自身の推奨する解決策は、スクリプトブロック自体でカレーを使用することです。

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

そしてHTMLで

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

カレーにご用心

コメントで述べたように、カレーには落とし穴があります。上記の例でhandleClick('parameter1')はクリック時に発生せず、レンダリング時に発生する最も一般的なもので、onclickで発生する関数を返します。つまり、この関数は引数として常に「parameter1」を使用します。

したがって、このメソッドを使用しても安全なのは、使用されるパラメーターが何らかの定数であり、一度レンダリングされると変更されない場合だけです。

これは私に別のポイントをもたらします:

1)パラメータを使用した定数の場合、別の関数を使用することもできます

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

2)値が動的であるがコンポーネント内で使用可能な場合、これはスタンドアロン関数で処理できます。

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

3)値が動的であるが、これが何らかの種類のスコープ(例:#eachブロックでレンダリングされたアイテムのリスト)に依存しているためにコンポーネントから利用できない場合、「ハッキー」アプローチがよりうまく機能します。ただし、その場合は、リスト要素をコンポーネントとして使用し、ケース2にフォールバックする方がよいと思います。

結論として:カレーは特定の状況下で機能しますが、その使用方法について十分に認識して注意している場合を除き、推奨されません。


3
これを行わないでください!インライン関数(on:click={() => handleClick('parameter1')})を作成するだけ
リッチハリス

1
それがあなたが対応していた提案だと気づきました。カリー化のアプローチに反対する理由は2つあります。1つ目は、何が起こっているのかすぐに明確にならないことです(人々は、クリックがhandleClick('parameter1')発生すると何が起こるのかを誤って考える傾向があります。2つ目は、パラメーターが変更されるたびにハンドラーを再バインドする必要があることを意味します。現在のところ、バグが発生しています。つまり、動作しませんsvelte.dev/repl/a6c78d8de3e2461c9a44cf15b37b4dda?version=3.12.1
Rich Harris

1
確かに、私はそのバグに自分で遭遇したことがないことを知りませんでした。次に、私が取り組んでいるコードベースでは、このようなパラメーターを渡さないでください。これらはほとんどの場合オブジェクトであり、機能するようです:svelte.dev/repl/72dbe1ebd8874cf8acab86779455fa17?version
Stephane Vanraes

私はいくつかのカレーの落とし穴と他の反射で私の答えを更新しました。入力ありがとう
Stephane Vanraes

はい、そうです、参照自体が変更されない限り(そして、根本的なバグもやがて修正されるでしょう)、オブジェクトで機能します
Rich Harris
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.