Как передать параметры на: нажмите в 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>

Это то, что даже документы не упоминается явно. Но да, вот так сейчас, я думаю .. Пока они не
Маниш

6
Это не хак, а как это работает . Это явно упоминается в руководстве svelte.dev/tutorial/inline-handlers
Рич Харрис,

3
Спасибо за ваши комментарии! Этот «хакерский способ» сделать это не так уж и плохо, но я бы осмелился сказать, что в документах и ​​учебниках об этом не очень ясно говорится . Может быть, это только я, хотя.
FelDev

Ответы:


5

TL; DR

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


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

ПОЧЕМУ мне нужна еще одна функция-обертка?

Если бы вы использовали только обработчик и передавали параметры, как бы это выглядело?

Вероятно, что-то вроде этого:

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

Но помните, handleClick("arg1")это то, как вы вызываете функцию мгновенно, и именно так и происходит, когда вы ее называете так, она будет вызываться, когда выполнение достигает этой строки, а не так, как ожидалось, НА КНОПКЕ CLICK ...

Следовательно, вам нужно объявление функции, которое будет вызываться только событием 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) {
  ...
}

Чтобы предоставить некоторые дополнительные сведения людям, которые также борются с этим, и это должно быть в документах, если это не так, вы также можете получить событие click в таком обработчике:

<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

Вот это с методом debounce и аргументом события:

<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')вариант, который в приведенном выше примере будет вызываться не при нажатии, а при рендеринге, возвращая функцию, которая, в свою очередь, будет запущена при нажатии. Это означает, что эта функция всегда будет использовать «параметр1» в качестве аргумента.

Поэтому использование этого метода будет безопасным только в том случае, если используемый параметр является некоторой константой и не изменится после того, как он будет представлен.

Это привело бы меня к другому вопросу:

1) Если в качестве константы используется параметр, вы также можете использовать отдельную функцию

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

2) Если значение является динамическим, но доступно внутри компонента, это все равно можно обработать с помощью отдельной функции:

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

3) Если значение является динамическим, но не доступно из компонента, поскольку оно зависит от некоторой области видимости (например, список элементов, отображаемых в блоке #each), подход «хакерский» будет работать лучше. Однако я думаю, что в этом случае было бы лучше, если бы сами элементы списка были компонентом и вернулись к случаю № 2.

В заключение: карри будет работать при определенных обстоятельствах, но не рекомендуется, если вы не очень хорошо осведомлены и не знаете, как его использовать.


3
Не делай этого! Просто создайте встроенную функцию ( on:click={() => handleClick('parameter1')})
Rich Harris

1
Просто понял, что это предложение, на которое вы отвечаете. Причина, по которой я советую придерживаться подхода с каррингом, двояка: во-первых, не сразу понятно, что происходит (люди склонны считать, что handleClick('parameter1')именно это происходит, когда щелчок происходит неправильно. Во-вторых, это означает, что обработчик должен быть отскочен при изменении параметров, Это неоптимально. В настоящее время есть ошибка, означающая, что она все равно не работает svelte.dev/repl/a6c78d8de3e2461c9a44cf15b37b4dda?version=3.12.1
Рич Харрис

1
Правда, я не знал об этой ошибке, никогда не сталкивался с ней сам. С другой стороны, в кодовой базе, над которой я работаю, мы никогда не передаем параметр, подобный этому, они почти всегда являются объектами, и это, кажется, работает: svelte.dev/repl/72dbe1ebd8874cf8acab86779455fa17?version=3.12.1
Стефан Ванрас

Я обновил свой ответ, добавив некоторые подводные камни и другие размышления. Спасибо за вклад
Стефан Ванрас

Ага, это будет работать с объектами, пока сама ссылка не изменится (и основная ошибка также будет исправлена ​​в должное время)
Rich Harris
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.