Як передати параметри на: натисніть на Svelte?


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
Rich Harris

3
Дякуємо за ваші коментарі! Цей "хакітний спосіб" зробити це не так вже й погано, але я б наважився сказати, що документи та підручник не дуже чіткі щодо цього. Можливо, це тільки я.
FelDev

Відповіді:


5

TL; DR

Просто перегорніть функцію обробника в іншу функцію, для елегантності використовуйте функцію стрілки


Ви повинні використовувати функцію оголошення, а потім викликати обробник з аргументами. Функція стрілки елегантна і хороша для цього сценарію.

ЧОМУ мені потрібна інша функціональна обгортка?

Якби ви використовували лише обробник і передавали параметри, як би це виглядало?

Можливо, щось подібне:

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

Але пам’ятайте, handleClick("arg1")саме так ви негайно викликаєте функцію, і саме це відбувається, коли ви поставите її таким чином, вона буде викликана, коли виконання досягне цього рядка, і не так, як очікувалося, НА КЛІТКУ КЛИКУ ...

Тому вам потрібна декларація функції, на яку буде викликатись лише подія клацання, і всередині неї ви зателефонуєте своєму обробнику стільки аргументів, скільки вам потрібно.

<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. Це означає, що ця функція буде завжди використовуватиме 'параметр1' як аргумент.

Тому використання цього методу було б безпечним лише в тому випадку, якщо використаний параметр є константою певного роду і не зміниться після його надання.

Це призведе мене до іншого моменту:

1) Якщо параметр використовується константа, ви також можете використовувати окрему функцію

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

2) Якщо значення є динамічним, але наявне в компоненті, це все ще може бути оброблено за допомогою окремої функції:

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

3) Якщо значення динамічне, але воно не доступне для компонента, оскільки це залежить від певної області застосування (наприклад: список елементів, винесених у блок #each), , підхід 'hacky' буде працювати краще. Однак я думаю, що в цьому випадку було б краще мати елементи списку як компонент і повернутися до справи №2

Підсумовуючи: при певних обставинах приготування кашлю буде працювати, але не рекомендується, якщо ви не дуже обізнані та обережні, як його використовувати.


3
Не робіть цього! Просто створіть вбудовану функцію ( on:click={() => handleClick('parameter1')})
Річ Гарріс

1
Щойно зрозумів, що це пропозиція, на яку ви відповідали. Причина, яку я раджу проти підходу до виклику, є двоякою - по-перше, менш одразу зрозуміло, що відбувається (люди схильні вважати, що handleClick('parameter1')це відбувається, коли відбувається натискання , неправильно. По-друге, це означає, що обробник потребує відбиття кожного разу, коли змінюються параметри, На даний момент є помилка, тобто все одно не працює svelte.dev/repl/a6c78d8de3e2461c9a44cf15b37b4dda?version=3.12.1
Rich Harris

1
Правда, я не знав про те, що ця помилка ніколи не стикався з нею сам. Потім знову в кодовій базі, над якою я працюю, ми ніколи не передаємо такий параметр, вони майже завжди є об'єктами, і це, здається, працює: svelte.dev/repl/72dbe1ebd8874cf8acab86779455fa17?version=3.12.1
Stephane Vanraes

Я оновив свою відповідь деякими кричущими підводними каменями та іншими роздумами. Дякую за внесок
Стефан Ванраес

Ага так, вона буде працювати з об'єктами, доки сама посилання не зміниться (і базова помилка виправиться також з часом)
Річ Гарріс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.